Din
Din

Reputation: 1

very long compilation times

I'm working on a large solution that has thousands of source files, some of them can have over a thousand includes due to the use of Boost and dependency problems. While compiling in parallel on a 12 core Xeon E5-2690 v2 machine (windows 7) it takes up to 4 hours to rebuild the solution using Waf 1.7.13. What can I do to speed things up?

Upvotes: 0

Views: 545

Answers (4)

JarkkoL
JarkkoL

Reputation: 1918

Some suggestions you could try relatively easily:

  1. Use distributed compilation using IncrediBuild or such
  2. Use "unity" builds, i.e. including several cpp files in a single cpp file and compiling only the unity cpp's (you can have a simple tool building the unity cpp's with given number of cpp files in each). Even though I'm not big fan of this technique due to its shortcomings I have seen it employed quite often in projects with bad physical structure to optimize compile & link times.
  3. Use "#pragma once" in headers
  4. Use precompiled headers
  5. Optimize redundant #include's in header files. I don't know if there's a tool for it, but you could easily build a tool which comments out #includes in headers and tries to compile them to see which ones are not needed.
  6. Profile #include file compilation speeds and focus on addressing the worst performers and the ones that are deepest in the #include chain. I.e. use forward declarations instead of #include's, etc.
  7. Buy more/better hardware

Upvotes: 0

The culprit is likely the structure of your project itself: the expected time for rebuilding is roughly proportional to the number of source files times the number of headers they include. With strong template based programming, that effort grows with the square of source files.

So, you have exactly two contrary options to get your total compilation time down:

  1. You reduce the number of headers included by each source file. That means you have to avoid any templates that use templates. Try to reduce inter-template dependencies as much as you can.

  2. Program only in headers and only use a single .cpp file which instanciates all the different templates in your application. This avoids any recompilation of a header.

    • A possible variant of this is to create a precompiled header from all header files in your project, so that precompiling the header takes the bulk of the building time.

Of course, option 2 means that there is no such thing as an incremental build, you will need to recompile the entire project everytime you compile. This can make your project entirely unmaintainable. So, I would strongly suggest to go for option 1. But that requires a different programming style (one that uses templates very sparingly) than your project seems to be written in.

In either case, there is no magic bullet: It is not likely possible to make a significant change to the compilation time without restructuring the entire project.

Upvotes: 0

pqnet
pqnet

Reputation: 6588

If refactoring to remove dependencies is not an option, and the build architecture is so unreliable that you have to clean and rebuild all from time to time (in a perfect world this should never happen), you can:

  • Improve your machine: use an SSD hard disk and/or lot of RAM. If the project has thousand of source files, you will need to hit the disk a lot of times, with random but cacheable accesses. For 12 core machine with hyper threading I would suggest no less than 24gb of ram, probably better going toward 32. You should measure what is your source code size and how much ram is used by the concurrent 24 compilers you can run in parallel.
  • Use a compiler cache. I don't know how to setup such environment from windows, and with your build system, so I can't suggest much here.

Upvotes: 0

Christian Hackl
Christian Hackl

Reputation: 27538

A few things that come to mind:

  • Use forward declarations and PIMPL.
  • Review your code base to see if you have created unnecessary templates when normal classes or functions would have been sufficient.
  • Try to implement your own templates in terms of non-generic implementations operating on void* where applicable, the templates serving merely as type-safe wrappers (see "Item 42: Use private inheritance judiciously" in "More Effective C++" for a nice example).
  • Check your compiler's documentation for precompiled headers.
  • Refactor your application's entire architecture so that there are more internal libraries and a smaller application layer, the goal being that in the long run the libraries become so stable that you don't have to rebuild them all the time.
  • Experiment with optimisation flags. See if you can turn down optimisation in several specific compilation units where optimisation doesn't make a measurable difference in execution speed or binary size yet signficantly increases compilation times.

Upvotes: 5

Related Questions