Inside niven, I've been using precompiled headers since the first
version. Read on for some insights I gained over the years.

Platform

The following is written while I was using the Microsoft Visual C++ 8.0
compiler. It is probably also true for earlier versions, but I cannot
check that.

Start point

niven had precompiled headers right from the beginning. They used to
contain often used internal headers and large parts of the STL
(map,vector, etc.). Over the time, a lot of headers from
Boost found their way into the precompiled
header. The last version I had compiled to a 47 MiB large .pch file.
Compilation time was roughly one minute for the core library, which was
already pretty good given the size and complexity of the source code.
I've been using the best practices for physically decoupling the code.
This means each header forward declared as much as possible and includes
were delayed so most of the happened in the .cpp file (where they
should be). In addition, often used headers were put into a single
precompiled header and compiled just once for the application.

The Fast & the Curious

Well, as always, fast was not fast enough for me (1 minute for a full
recompile on my notebook - as if I would have a spare minute :) ). I've
taken a deep look at what should really go into the precompiled header,
commenting everything out first. Step by step, I could strip down
approximately half of my precompiled header, reducing the compile time
down to 37 seconds - now my notebook is just as fast as my desktop
previously. The .pch file is now 30 MiB - a 33% reduction.

Lessons learned

The most expensive headers are those taking huge parts of the STL and
other template magic with them. For example, including
<boost/bind.hpp> can easily double the compile time per source file!
Compared to this, files with a lot of preprocessor magic (in my case,
<boost/signals.hpp>) don't make a visible difference. I've moved them
out and back of the precompiled header, but I could not measure any
improvement - seems the preprocessor is really fast. Also, be aware that
some headers tend to include stuff you don't think about usually. For
example, <boost/signals.hpp> includes <list> - after removing the
former from the precompiled header, some parts of my code complained
about not finding the latter. An interesting result of this is that
eventually, the compiler is able to process a lot of files per second
now. You don't see individual files popping up in the output window but
batches of three or even more files - woohoo! Link time and precompiled
header generation is now dominating the build time. I presume most of it
is spent in the interprocedural optimization step, as the core library
is linking basically against the bare minimum you have to link
(C-Runtime, C++-Runtime, some Windows specific libraries). As soon as I
get a chance, I'll try with the Intel C++ 9.1 Compiler to see how big
the difference is over there.