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 | edit source]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 | edit source]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 | edit source]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 | edit source]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 | edit source]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 | edit source]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 | edit source]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.