This Article describes various optimization techniques in C. It explains how to optimize macros, initializations, and data structures in C and how to remove invariants and inefficiencies in loops.
To optimize a program written in C, you need to consider its execution time. You can calculate the amount of time taken for each function to execute by using the following features available in C:
- Stdio function: Uses the getc() and putc() macros, which function faster than user-defined function calls.
- memcpy() function: Reduces execution time.
- Single precision operator: Increases the speed of operation.
In C, you can also optimize the code during program compilation. To do so, you need to know the execution time of operators and library functions such as *, +, and strcpy(). All operators and functions do not take the same amount of time to execute.
Some operators and library functions available in C with their execution time are as follows:-
|Operator/Library Function||Time (in microsec)|
|float * float||0.049|
|float + float||0.049|
|Int ^ int||0.050|
|Int * int||0.198|
Some operators, such as Int–int and array index, take less time, and some operations take longer time to execute. For example, multiplication of integers takes longer than subtraction.
Memory hierarchy also affects the performance. If you want your program to run fast, you need to assign memory at the top of the hierarchy and you need to know how the memory hierarchy works.
The order in which you should use memory in a program to improve speed is:
- CPU registers: A storage device that you use to access data.
- RAM: Permanent memory that you use to access data.
- ROM: Temporary memory that is slower than RAM.
- Virtual Memory: A very slow temporary memory, which takes thousands of clock cycles to access data.
[P.S: Clock cycle is the time between two pulses of a clock in memory. Some processors can execute one instruction per clock cycle while others can execute multiple instructions per clock cycle.]
You need to identify the performance of algorithms to optimize the code in C. The most commonly-used method to measure the performance of the algorithm is the O-notation. The O-notation is a formula that calculates resource usage.
Techniques for Optimization
There are three types of techniques for optimizing code in C:
- Compute-bound techniques
- Memory-bound techniques
- Input/Output-bound techniques
Compute-bound techniques involve computing the time taken to execute operators and functions. Compute-bound techniques include:
- Loop unrolling
- Loop jamming
- Loop invariants computation
- Loop inversion
- Tail recursion elimination
- Table look up
In memory-bound computations, you need to take into account the memory that the program uses. The use of memory from the lower parts of the memory hierarchy increases the execution time. You need to use memory from the appropriate level while running programs. Memory-bound techniques include:
- Locality of reference
- Row-Major addressing
- Padding reduction
- Memory leaks
In Input/Output (I/O) bound optimization, the sequential access and random access methods are used to reduce the time required to retrieve information.
A buffered I/O is faster than an unbuffered I/O. You can use read() and write() functions with large buffers. You can use mmap() to reduce time required to retrieve information. Mmap() maps the process’s address space with shared memory or file.
Other Optimization Techniques
You can also optimize code by rewriting time-critical functions in assembly language programming. Changing the program in C to assembly language is difficult.You can change only the critical functions into assembly code.
To optimize the code in C, use a compiler to generate an assembly language. You can also optimize your code by changing the source of the hardware, such as upgrading the CPU, adding a co-processor, changing Internet connection speed, and installing a high-speed RAID disk array.
You can install compilers from several vendors to compile programs with time-critical functions and check which compiler is faster.
You can avoid using increment and decrement operators, such as ++ and –, in loops. Some other ways to increase speed are:
- Minimize the use of global variables in the program.
- Declare all functions other than global variables as static within the file.
- Use word size variables such as int and float instead of char, short, and double.
- Avoid using recursion.
- Avoid using the sqrt() function as it is CPU intensive.
- Use single-dimensional arrays.
- Do not split closely related functions into separate files.
- Use puts() function instead of the printf function.
- Use unformatted/binary file access instead of formatted file access.
- Use mallopt() if the compiler supports this function to control malloc function.
- Use macros instead of small functions to save CPU time.