views:

164

answers:

4

Boost rocks, it is great and extremely powerful, but I hate it everytime I build solution in my Visual Studio 7.1.

It seems Boost has impact on build time (not positive). I cannot remove all Boost usage from my project to compare build times but I tried it on small projects and the difference is meaningful.

I guess the problem is that Boost consists of thousands of header files which include themselves very extensively. So, when I include, say, boost/function.hpp into my header file, it may lead to including hundred of Boost headers.

Is there someone who experienced the same? Any ideas how to solve it?

Rough thoughts:

  1. Add boost to precompiled headers? At least they will be parsed and kept in one file
  2. Do explicit instantination for some Boost templates?
  3. Prepare Boost headers somehow?
  4. Do not include Boost to header files (sounds unreal)
  5. ...

PS. Yep, Boost also uses hardcore templating that pretty hard to compiler I guess, so thousands of header files are not the only problem.

A: 

As you mentioned in your post, the boost code contains a lot of template code that require a lot of CPU cycles for compilation. The overhead from multiple header files is very small compared to that.

The first thing you need to do is find out which header file or which line of code is responsible for the delay in compilation. Often it is not the inclusion of the header file, but the usage of one of its classes/functions in your own code that is causing the delay. You can isolate the responsible code by commenting out pieces of your code until compilation is fast again, and then uncommenting your pieces of code until compilation is slow again. Then you can decide whether you want to replace the slow code with something else or not. It's up to you to weigh the pros and cons here or compilation speed vs nifty boost code.

There are a few other things you can do as well:

  • clean up unneeded include statements, esp in your headers
  • in your header files, replace includes with forward declarations (where possible)
  • get a faster computer :D
StackedCrooked
It seems it won't work to me. We already use very fast computers but the build process takes several hours... And how to "find out which header file or which line of code is responsible for the delay in compilation" automatically? Codebase is huge.
bocco
Do you have any basis for this answer? It seems counterintuitive, and simple tests (start with an empty main(), and then add includes from the STL piecemeal) shows that including a file has a very real cost. What am I missing? Thanks!
Kim Gräsman
I'm not denying that including files has a cost. However, it is my experience that sometimes a bigger cost comes from usage of certain boost code, than from the include itself.
StackedCrooked
I see, thanks. I think your answer under-emphasizes the cost of inclusion, though. Granted, Boost is heavily templated, so actually compiling the code will be time-consuming, but even in non-templated code performing an include with all it entails is sort of a constant overhead.
Kim Gräsman
A: 

Including Boost header files only when they are really necessary makes sense. Headers including other headers cause stress to IO and has great impact to compile time. Forward declaration helps to some point, but with Boost it can be real pain.

Using external guards in header files avoids unnecessary loading. Like this:

#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
#   include <boost/shared_ptr.hpp>
#endif

Another way to avoid header cascade is to use "pimpl"-idiom, especially when dealing with complex classes. Then complex Boost stuff can be included and used only by that compilation unit. Downside is that interface should be designed so that no Boost specific stuff is required. However, breaking depencies might be a good thing too.

Virne
External include guards can be risky if it's not your code -- does Boost leave a guarantee that they won't change the include guard format?
Kim Gräsman
Yeah. They can be risky. Sometimes even when it is your own code. :)Far as I know, there is no guarantee that Boost header guards will stay like that. However, I am willing to take that risk. If they happen to change, it's just bunch of compiler errors that can easily be pointed to not included file.
Virne
Either that, or you optimization scheme is silently broken because you're checking for BOOST_SHARED_PTR_HPP_INCLUDED when the actual (for-the-sake-of-the-argument) name is BOOST_SHAREDPTR_INC -- and your build is suddenly a little slower.
Kim Gräsman
+8  A: 

I like also boost a lot

  • Use the precompiled header like you told (that brings most)
  • When using linked libraries check if you really need them (linking is also quite slow)

Another maybe stupid hint, but was the main source of performance loss on my computer:

  • check if your antivirus makes an on-access-scan and disable it for the header & source directories (boost and your projects)
jdehaan
Thumb up for antivirus note! They usually cause more harm than viruses do.
Virne
The anti-virus one has hit me before.
Martin York
Good point about anti-virus, but it is already disabled for build dirs. We also use separate HDD for project files and outputs. It helps a lot.
bocco
+2  A: 

Naturally, including boost leads to longer compilations times - just like including any library does. Being (mostly) a template library offcourse leads to quite big performance penalty as all of the logic is implemented in the headers.

  1. I've had good results including (a subset of) boost in precompiled headers. However, I belive that the gain is greatest with MSVC 9. On MSVC 7 I have seen several reports saying that precompiled headers of templates frequently leads to performance penalty. Another crucial aspect determining if you'll see performance gain is to include the appropiate headers in the precompiled header. Only include headers you frequently use, and make sure they are never changed (that is, think three times before including your own headers here)

  2. I do not know if explicit instantination has any effect, even though I doubt it. If anyone has seen any results on this (regardless compiler), it would be very interesting.

  3. "Preparing" boost headers sounds like altering them which sounds like a very bad idea to me. You don't want to end up maintaining customized headers...

  4. May not be so unreal as you might think. Always use as many forward declarations as possible to reduce the "footprint" of each header file. Consider using the Pimpl pattern to avoid including boost headers that are not reflected in the public interface of your class (offtopic: I consider Pimpl to often be unnecessary. Instead I try to slice the classes into smaller pieces, acheiving the same result in a "cleaner" fashion). Don't be afraid to include general, common classes (e.g. shared_ptr) as long as you're consistent in the usage of these classes (if your using them in all your classes you wont see much gain in hiding them away from one header).

  5. Upgrading MSVC (to support parallel builds) will help. However, this is always an issue in C++. To minimize the problem, you need to be very strict and follow guidelines to reduce the footprint of your headers. Now and then you should look through the include-clauses and make sure there are nothing unnecessary included. If you're list of includes done in the header is getting long you're probably doing something wrong - most includes should only be in the cpp.

larsm