An executable file with multiple source files is slower than an executable file with a single source file

I had a single source file that had all the class definitions and functions.

For a better organization, I moved class declarations (.h) and implementations (.cpp) to separate files.

But when I compiled them, it led to a slower execution than the one I get from a single-source executable. Its about 20-30 seconds slower for the same entry. I am changing any code.

Why is this happening? And how can I do it faster?

Update: The execution of one source completes after 40 seconds, while the executable file with several source files takes 60. And I mean the runtime, not the compilation.

+8
c ++ optimization gcc
source share
3 answers

I think your program runs faster when it compiles as a single file, because in this case the compiler has more information needed to optimize the code. For example, it can automatically embed some functions, which is not possible with a separate compilation.

To make this faster, you can try turning on the link optimizer (or the whole program optimizer) with this option: -flto .


If the -flto option -flto not available (and is only available with gcc 4.6), or if you do not want to use it for any reason, you have at least 2 options:

  • If you divided the project only for better organization , you can create this file with one source file (for example, all.cxx ) and #include all source files (all other *.cxx files). Then you only need to build this all.cxx , and all compiler optimizations will be available again. Or, if you split it the same way to make the compilation incremental, you can prepare 2 build options: incremental build and build units. First, all individual sources are built, the second - only all.cxx . Read more about it here .
  • You can find functions that would cost you productivity after dividing the project, and move them either to the compilation unit where they are used, or to the header file. To do this, start with profiling (see " What can I use to profile C ++ code on Linux? "). Further study of parts of the program that significantly affect program performance; There are two options here: either use the profiler again to compare the results of incremental and single builds (but this time you need a sampling proxy, such as oprofile, while a profiler tool, like gprof, is most likely too heavy for this task); or apply the "experimental" strategy described by gbulmer .
+10
source share

This is probably due to the optimization of link time . When all your code is in one source file, the compiler has more knowledge of what your code does so that it can perform more optimizations. One such optimization is this: the compiler can only inline a function if it knows its implementation at compile time!

These optimizations can also be performed at connection time (rather than compilation time) by passing the -flto flag to gcc, both for compilation and for the link phase (see here ).

+5
source share

This is a slower approach to return to a faster runtime, but if you want to better understand what causes big changes, you can do a few “experiments”

One experiment would be to find which function may be responsible for large changes. To do this, you can "profile" the execution time of each function.

For example, use GNU gprof, part of GNU binutils: http://www.gnu.org/software/binutils/
Docs: http://sourceware.org/binutils/docs-2.22/gprof/index.html

This will measure the time spent by each function in your program and where it was called from. Performing these measurements is likely to have the “Heisenberg effect”; measurements will affect program performance. So you can try an experiment to determine which class has the biggest difference.

Try to get an idea of ​​how the runtime differs between the source code of a class in the main source and the same program, but with the class compiled and linked separately.

To get the implementation of the class in the final program, you can either compile it, or link it, or simply include it in the "main" program, and then compile the main one.

To make it easier to swap, you can enable or disable #include with #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: #include using command line flags for the compiler, for example

 g++ -DCLASSA -DCLASSB ... main.c classc.cpp classd.cpp classf.cpp 

It may take just a few minutes to generate permutations of -Dflags and command references. Then you will have the opportunity to generate all the compilation permutations "in one unit" individually, and then run (and time) each.

I assume your header files are wrapped in plain

 #ifndef _CLASSA_H_ #define _CLASSA_H_ //... #endif 

Then you will have some information about the important class.

These experiments may provide some insight into the behavior of the program and the compiler, which may stimulate some other ideas for improvement.

+1
source share

All Articles