Introduction to Optimization

Optimization is the process of transforming a piece of code to make more efficient (either in terms of time or space) without changing its output or side-effects. The only difference visible to the code’s user should be that it runs faster and/or consumes less memory. It is really a misnomer that the name implies you are finding an “optimal” solution— in truth, optimization aims to improve, not perfect, the result.

Here I am trying to cover some code optimization techniques which I learned from my mistakes.

Consider some basic optimization rules.

1. Before preceding with code optimization, devolop a reliable non optimized version of the same code. This means before you start optimizing the code make sure your program runs correctly
2. Use algorithmic optimization, rather than feature of the system, to achieve the greatest performance gain.
3. Don’t assume code optimization with assembly implementation
4. Don’t think my compiler ill optimize everything for me.

When and Where To Optimize

There are a variety of tactics for attacking optimization. Some techniques are applied to the intermediate code, to streamline, rearrange, compress, etc. in an effort to reduce the size of the abstract syntax tree . Others are applied as part of final code generation—choosing which instructions to emit, how to allocate registers and when/what to spill, and the like. And still other optimizations may occur after final code generation, attempting to re-work the assembly code itself into something more efficient.
Optimization can be very complex and time-consuming; it often involves multiple subphases,

some of which are applied more than once. Most compilers allow optimization to be turned off to speed up compilation (gcc even has specific flags to turn on and off individual optimizations.)

Integers

We should use unsigned int instead of int if we know the value will never be negative. Some processors can handle unsigned integer arithmetic considerably faster than signed (this is also good practice, and helps make for self-documenting code).

So, the best declaration for an int variable in a tight loop would be:
register unsigned int variable_name;
although, it is not guaranteed that the compiler will take any notice of register, and unsigned may make no difference to the processor. But it may not be applicable for all compilers.

switch() instead of if…else…
For large decisions involving if…else…else…, like this:

if( val == 1)
dostuff1();
else if (val == 2)
dostuff2();
else if (val == 3)
dostuff3();

It may be faster to use a switch:

switch( val )
{
case 1: dostuff1(); break;
case 2: dostuff2(); break;
case 3: dostuff3(); break;
}

In the if() statement, if the last case is required, all the previous ones will be tested first. The switch lets us cut out this extra work. If you have to use a big if..else.. statement, test the most likely cases first.

STRING OPERATIONS

Most of the C library str* and mem* functions operate in time proportional to the length(s) of the string(s) they are given. It’s quite easy to loop over calls to these and wind up with a significant bottleneck. Some things that may ease the situation:

    strlen

Avoid calling strlen() during a loop involving the string itself. Even if you’re modifying the string, it should be possible to rewrite it so that you set x = strlen() before the loop and then x++ or x– when you add or remove a character.

    strcat

When building up a large string in memory using strcat, it will scan the full (current) length of the string on Each call. If you’ve been keeping track of the length anyway (see above) you can index directly to the end of the string and strcpy or memcpy to there.
strlen(s) == 0
Empty string tests are common, and even experienced programmers may use strlen for this purpose. But if the strings you are working with are of substantial size, strlen will dutifully check each character until it finds the NULL terminator. Replace with *s == ‘\0′ which saves the function call overhead plus it only has to check the first character. There can be a substantial improvement if your character strings are fairly long.
strcpy(s, “”)

*s = ‘\0′ works just fine and saves a function call.

strncpy(s, t, n)

Be aware that strncpy pads short strings with 0′s. Except for the first one, which terminates the string, the extra zeroes are typically never used, so some time is wasted, though typically not very much.

memcpy/memmove

Generally, memcpy is faster than memmove because it can assume that its arguments don’t overlap. If you are tempted to replace these with your own versions, be sure to verify that your version (a) works and (b) is faster.

Ref : Internet Libs