10

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.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
questions
  • 2,337
  • 4
  • 24
  • 39
  • 3
    20-30 seconds out of how long in total? – Oliver Charlesworth Mar 16 '12 at 18:54
  • 2
    Also, are you linking/compiling on the command line, or using an IDE like VS? It's obviously going to take longer to link the source files together than if everything was in one file, but 20-30 seconds difference is far too long for all but huge applications. If I had to guess, and this is purely a guess, I'd say that you'd have to spread your source around thousands of files to get those kind of build times. – prelic Mar 16 '12 at 18:56
  • 1
    Are you sure you're not compiling using "debug" flags? 20 seconds is **a lot**. – mfontanini Mar 16 '12 at 18:58
  • 2
    @prelic: he stated "(...)it resulted in a slower executable than the one(...)". He means 20 seconds of run-time, not compilation time. – mfontanini Mar 16 '12 at 19:05
  • @OliCharlesworth- Out of 60. The single source executable completes in 40 and the multiple source takes 60+ – questions Mar 16 '12 at 19:05
  • Which compiler are you using? Using which flags? – mfontanini Mar 16 '12 at 19:06
  • Can you paste the way you are invoking gcc? Providing all the command line arguments. – mfontanini Mar 16 '12 at 19:07
  • In C++ source files (.cpp) are always only compiled one time; however, header files (.h files) are compiled once per compiler execution. Each header file needs to be recompiled because there could be different effects made from the preprocessor. Since each header file is often compiled many times, headers compilation is often responsible for a large part of total C++ compilation time. You can reduce this part of compilation time by using forward declarations or precompiled headers. – Flot2011 Mar 16 '12 at 19:08
  • 2
    Are the size of the executables comparable? The compiler should produce similar machine instructions, regardless of how the source is organized. We might have to see some code to see why you're having problems. Since we're talking running performance here, I'm guessing the problem is hiding somewhere in the code, and not the way you're building it. – prelic Mar 16 '12 at 19:08
  • `gcc -o2 -std=c++0x -I ./ test.cpp -o test -lboost_thread` – questions Mar 16 '12 at 19:15
  • Impossible to say without code. Make a small reproduction. – David Heffernan Mar 16 '12 at 19:15
  • Oops..I'm using g++, those two confuse me always – questions Mar 16 '12 at 19:35

3 Answers3

11

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:

  1. If you split your project only 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.
  2. You can find functions, that cost you performance after splitting the project, and move them either to the compilation unit, where they are used, or to header file. To do this, start with profiling (see "What can I use to profile C++ code in Linux?"). Further investigate parts of the program, that significantly impact program's performance; here are 2 options: either use profiler again to compare results of incremental and unity builds (but this time you need a sampling profiler, like oprofile, while, an instrumenting profiler, like gprof, most likely, is too heavy for this task); or apply 'experimental' strategy, as described by gbulmer.
Community
  • 1
  • 1
Evgeny Kluev
  • 24,287
  • 7
  • 55
  • 98
6

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).

Thomas
  • 174,939
  • 50
  • 355
  • 478
1

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.

gbulmer
  • 4,210
  • 18
  • 20