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?
-
Don't rebuild the entire project every time? – Oliver Charlesworth Aug 17 '14 at 10:39
-
If I only could... but a rebuilt of the whole project is unfortunately often required – Din Aug 17 '14 at 10:41
-
It sounds like that's what you should be addressing first, then! – Oliver Charlesworth Aug 17 '14 at 10:44
-
@Din This sounds very much like a ***bad architecture*** problem. The only real solution for this is going to refactor your project dependencies. As a 1st step go through headers, and exchange `#include` statements with forward declarations, whenever possible. – πάντα ῥεῖ Aug 17 '14 at 10:46
-
buy more machines, they are cheaper than programmer time spent in refactoring. If you have a cluster of ~20 machines such as the one you describe you could be able to compile the whole thing in about 10 minutes. – pqnet Aug 17 '14 at 10:48
-
@pqnet Also a valid (but short term) solution. – πάντα ῥεῖ Aug 17 '14 at 10:49
-
@πάνταῥεῖ and also mostly liked by management staff. Or you could outsource the whole project – pqnet Aug 17 '14 at 10:58
-
@pqnet: I do not think that many managers would realise that buying more machines can easily be cheaper than programmer working hours. – Christian Hackl Aug 17 '14 at 11:00
-
1@ πάντα ῥεῖ I have done it already... – Din Aug 17 '14 at 11:00
-
1@pqnet Architectural flaws are most likely to be ignored by management staff, if you don't fight against them and bring in the cost facts to convince them. Unfortunately most projects end up in a mess as described in the OP's question, if these actions don't take place. – πάντα ῥεῖ Aug 17 '14 at 11:01
-
2"thousands of files" is not necessarily a mess. The need to recompile them all often _is_ indeed a mess though – pqnet Aug 17 '14 at 11:11
-
Agree with @pqnet: the culprit here is your unreliable build system itself. Any of the advice given below (so far) is really just a workaround. – Oliver Charlesworth Aug 17 '14 at 12:39
-
This problem is perhaps similar to a performance tuning problem in that you should first identify what causes the most dependencies before starting to make changes. I wonder if there is a good tool for that? – user2672165 Aug 17 '14 at 17:41
4 Answers
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.

- 27,051
- 3
- 32
- 62
-
Additional info on forward declarations: http://stackoverflow.com/questions/553682/when-can-i-use-a-forward-declaration – user2672165 Aug 17 '14 at 17:18
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.

- 6,070
- 1
- 30
- 51
-
we have 32gb of RAM on all of our machines, and we are using SSD drives on some of them, though the SSD got us some improvement - it is not something significant. – Din Aug 17 '14 at 11:19
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:
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.
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.

- 38,891
- 9
- 62
- 106
Some suggestions you could try relatively easily:
- Use distributed compilation using IncrediBuild or such
- 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.
- Use "#pragma once" in headers
- Use precompiled headers
- 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.
- 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.
- Buy more/better hardware

- 1,898
- 11
- 17
-
Beware of unity builds, C++ is very sensitive to the declarations being brought in due to overload resolution, so unity builds can (in some cases) break things... and that's a hard thing to track. – Matthieu M. Aug 17 '14 at 12:43