Reducing function-call overhead
When you write a function or call a library function, consider the following guidelines:
- Call a function directly, rather than using function pointers.
- Use const arguments in inlined functions whenever possible. Functions with constant arguments provide more opportunities for optimization.
- Use the restrict keyword for pointers that can never point to the same memory.
- Use #pragma disjoint within functions for pointers or reference parameters that can never point to the same memory.
- Declare a nonmember function as static whenever possible. This can speed up calls to the function and increase the likelihood that the function will be inlined.
- Usually, you should not declare all your virtual functions inline. If all virtual functions in a class are inline, the virtual function table and all the virtual function bodies will be replicated in each compilation unit that uses the class.
- When declaring functions, use the const specifier whenever possible.
- Fully prototype all functions. A full prototype gives the compiler and optimizer complete information about the types of the parameters. As a result, promotions from unwidened types to widened types are not required, and parameters can be passed in appropriate registers.
- Avoid using unprototyped variable argument functions.
- Design functions so that they have few parameters and the most frequently used parameters are in the leftmost positions in the function prototype.
- Avoid passing by value large structures
or unions
as function parameters or returning a large structure or a union. Passing
such aggregates requires the compiler to copy and store many values. This is worse in C++ programs in which class objects
are passed by value because a constructor and destructor are called
when the function is called. Instead, pass or return a pointer
to the structure or union, or pass it by reference. Homogeneous structs, unions and arrays
that meet one of the following conditions can be efficiently passed
as value parameters or returned as function results:
- Contain only up to eight floating-point values of the same type where complex is counted as two.
- Contain up to eight vector values or values processed in vector registers.
- Pass non-aggregate types such as int and short or small aggregates by value rather than passing by reference, whenever possible.
- If your function exits by returning the value of another function with the same parameters that were passed to your function, put the parameters in the same order in the function prototypes. The compiler can then branch directly to the other function.
- Use the built-in
functions, which include string manipulation,
floating-point, and trigonometric functions, instead of coding your
own. Intrinsic functions require less overhead and are faster than
a function call, and they often allow the compiler to perform better
optimization.
Many functions from the C++ standard libraries are mapped to optimized built-in functions by the compiler.
Many functions from string.h and math.h are mapped to optimized built-in functions by the compiler.
- Selectively mark your functions for inlining using the inline keyword. An inlined function requires less overhead and is generally faster than a function call. The best candidates for inlining are small functions that are called frequently from a few places, or functions called with one or more compile-time constant parameters, especially those that affect if, switch, or for statements. You might also want to put these functions into header files, which allows automatic inlining across file boundaries even at low optimization levels. Be sure to inline all functions that only load or store a value, or use simple operators such as comparison or arithmetic operators. Large functions and functions that are called rarely are generally not good candidates for inlining. Neither are medium size functions that are called from many places.
- Avoid breaking your program into too many small functions. If you must use small functions, you can use the -qipa compiler option to automatically inline such functions and use other techniques to optimize calls between functions.
- Avoid virtual functions and virtual inheritance unless required for class extensibility. These language features are costly in object space and function invocation performance.