I had a single source file which had all the class definitions and functions.
For better organization, I moved the class declarations(.h) and implementations(.cpp) into separate files.
But when I compiled them, it resulted in a slower executable than the one I get from single source executable. Its around 20-30 seconds slower for the same input. I dint change any code.
Why is this happening? And how can I make it faster again?
Update: The single source executable completes in 40 seconds whereas the multiple source executable takes 60. And I'm referring to runtime and not compilation.
I think, your program runs faster when compiled as a single file because in this case compiler has more information, needed to optimize the code. For example, it can automatically inline some functions, which is not possible in case of separate compilation.
To make it faster again, you can try to enable link-time optimizer (or whole program optimizer) with this option: -flto
.
If -flto
option is not available (and it is available only starting with gcc 4.6) or if you don't want to use it for some reason, you have at least 2 options:
for better organization
, you can create a single source file (like all.cxx
) and #include
all source files (all other *.cxx
files) to this file. Then you need to build only this all.cxx
, and all compiler optimizations are available again. Or, if you split it also to make compilation incremental, you may prepare 2 build options: incremental build and unity build. First one builds all separate sources, second one - only all.cxx
. See more information on this here.This probably has to do with link time optimization. When all your code is in a single source file, the compiler has more knowledge about what your code does so it can perform more optimizations. One such optimization is inlining: the compiler can only inline a function if it knows its implementation at compile time!
These optimizations can also be done at link time (rather than compile time) by passing the -flto
flag to gcc, both for the compile and for the link stage (see here).
This is a slower approach to get back to the faster runtime, but if you wanted to get a better understanding of what is causing the large change, you could do a few 'experiments'
One experiment would be to find which function might be responsible for the large change. To do that, you could 'profile' the runtime of each function.
For example, use GNU gprof, part of GNU binutils:
http://www.gnu.org/software/binutils/
Docs at: http://sourceware.org/binutils/docs-2.22/gprof/index.html
This will measure the time consumed by each function in your program, and where it was called from. Doing these measurements will likely have an 'Heisenberg effect'; taking measurements will effect the performance of the program. So you might want to try an experiment to find which class is making the most difference.
Try to get a picture of how the runtime varies between having the class source code in the main source, and the same program but with the class compiled and linked in separately.
To get a class implementation into the final program, you can either compile and link it, or just #include it into the 'main' program then compile main.
To make it easier to try permutations, you could switch a #include on or off using #if:
#if defined(CLASSA) // same as #ifdef CLASSA
#include "classa.cpp"
#endif
#if defined(CLASSB)
#include "classb.cpp"
#endif
Then you can control which files are #included using command line flags to the compiler, e.g.
g++ -DCLASSA -DCLASSB ... main.c classc.cpp classd.cpp classf.cpp
It might only take you a few minutes to generate the permutations of the -Dflags, and link commands. Then you'd have a way to generate all permutations of compile 'in one unit' vs separately linked, then run (and time) each one.
I assume your header files are wrapped in the usual
#ifndef _CLASSA_H_
#define _CLASSA_H_
//...
#endif
You would then have some information about the class which is important.
These types of experiment might yield some insight into the behaviour of the program and compiler which might stimulate some other ideas for improvements.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With