Optimizing C++/Code optimization/Run-time support

C++ run-time support routines obviously have a significant cost, because otherwise such behavior would have be inlined. Here techniques are presented to avoid the language features that cause an implicit call to costly run-time support routines.

The typeid operator

edit

Instead of using the typeid operator, use a virtual function.

Such operator may take more time than a virtual function call.

The dynamic_cast operator

edit

Instead of the dynamic_cast operator, use the typeid operator, or, better, a virtual function call.

Such operator may take a time noticeably longer than a virtual function call, and longer also than the typeid operator.

Empty exception specification

edit

Use the empty exception specification (that is, append throw() to the declaration) for the functions you are sure will never throw exceptions.

In C++11 use noexcept instead.

Some compilers use such information to simplify the bookkeeping needed to handle exceptions.

The try/catch statement

edit

For every bottleneck, move before the bottleneck the try keywords, and after the bottleneck the matching catch clauses.

In other words, hoist try/catch statements out of bottlenecks.

The execution of a try/catch statement sometimes is free of charge, but other times causes as a slowdown. Avoid the repeated execution of such block inside bottlenecks.

Floating point vs integer operations

edit

If the target processor does not contain a floating point unit, replace floating point functions, constants and variables with the corresponding integer functions, constants and variables; if the target processor contains only a single precision floating point unit, replace double functions, constants and variables with their float correspondents.

Present processors for desktop or server computers contain dedicated hardware for floating point arithmetic, both at single and at double precision, and therefore such operations are almost as fast as their integer correspondents.

Instead, some processors for embedded systems do not contain dedicated hardware for floating point arithmetic, or contain hardware able to handle only single precision numbers. Therefore, in such systems, the operation that cannot be performed by hardware are emulated by very slow library functions. In such case, it is much more efficient to use integer arithmetic, or, if available in hardware, single precision floating point arithmetic.

To handle fractional numbers by using integer operations, every number is to be meant as multiplied by a scale factor. To do that, every number is multiplied by such factor at input, and is divided by the same factor at output, or vice versa.

Number to string conversion

edit

Use optimized functions to convert numbers to strings.

The standard functions to convert an integer number to a string or a floating point number to string are rather inefficient. To speed up such operations, use non-standard optimized function, possibly written by yourself.

Use of cstdio functions

edit

To perform input/output operations, instead of using the C++ streams, use the old C functions, declared in the cstdio header.

C++ I/O primitives have been designed mainly for type safety and for customization rather than for performance, and many library implementation of them turn out to be rather inefficient. In particular, the C language I/O functions fread and fwrite are more efficient than the fstream read and write member functions.

If you have to use C++ streams, use "\n" instead of std::endl since std::endl also flushes the stream.