Precompiled headers

Forums: 

Just wonder if precompiled headers will be something that will be implemented in the new cmake system? The speed gain (in MSVC at least) is *so* much that I wonder why you didn't do this before! It's a matter of minutes vs. hours!
Also it's pretty easy to implement, and can be done out-of-source, I'll be happy to give advice if you need.

Kirill Gavrilov's picture

Probably you can share your experience and show actual number of building time with and without precompiled headers on your system?

QbProg's picture

I didn't test the actual version, but I can quote myself when I implemented PCH in OCE 0.3:
"In my system I get 5/6 mins for a full rebuild, but only with precompiled headers. Without them,
it was around 30/40 minutes :) With my old computer around 3 hours! hehehe"

I can confirm the gains in recent oce builds. Using GCC on linux I only noticed a 30% gain, but with much more drawbacks!
Note that I can achieve these times using PCH+cl /MP+parallel msbuild
---
Basically a precompiled header is generated from a .cpp file which contains a .h that includes the most used headers (mostly system libraries). So you basically:
1) generate a .pch from the cpp file containing only that .h file
2) you include the precompiled.h file in each .cpp file as FIRST include
the precompiled header is usually known as stdafx.h , but I prefer "Precompiled.h"
3) You set the compilation option that specify the name of that special .h file

the rules of thumb are the following:
- Precompiled headers are a private thing , so the library users are not affected by this, only the library build process
- NEVER include the precompiled.h in the .h files, only use it in .cpp files
- You don't have to change the sources to add the precompiled include. There's an option in the compiler to force the inclusion of the precompiled file at the top of each module (/FI)
- not every .cpp file is suitable to use precompiled headers, mostly because .h files that get included multiple times or that depend on a particular order. These modules can be compiled normally.

The drawbacks:
- each library needs a specific Precompiled header to be added. The precompiled header generation is done on top of the library build, and is not parallelized. So , the more you parallelize your build (using /CL) ,the less you see the gain (but you'll never beat pch)
- every time an header contained in the PCH is changed, you'll need to rebuild the whole library
- GCC has very bad PCH support and much more harder to achieve. Also, trying to build the PCH with parallel make will hang your system badly because of the resource usage. In this case pch would be useful for a single-shot build with no later modifications

notes about OCC:
- some classes , in particular in TKernel ,are not suitable. I remember that OSD_ didn't work very well. So you'll need to disable PCH for these files
- OCC doens't depend too much on c++ std so it builds relatively fast even without PCH. Suggesting PCH also for your users would make a big benefit for them
- if you are developing/changing headers PCH become annoying

That's it. To have an hint on how is implemented in CMake , feel free to take a look at OCE.

Mikhail Sazonov's picture

It would be good to have PCH as an option in cmake build. I do frequent rebuild of OCCT several versions. For this activity it may be helpful. Also I frequently alter source code including header files of OCCT, so in this activity I would like to have PCH turned off.
Dear QbProg, if you have enough knowledge of both cmake and OCCT, and especially that you have experience of such thing in OCE, you can propose a patch for OCCT. For that, please register a bug in OCCT bug tracker and create a branch in OCCT git repository. This branch will be reviewed, tested and, if success, integrated in master.

Mikhail

Andrey BETENEV's picture

Hello QbProg,

Thank you for highlighting this subject!

I have measured times of building current OCE with and without PCH (Visual Studio 2010 x64), the times are 32 min and 9 min respectively. Thus the gain is ~3.5 times.

The problem is that this kind of acceleration will unlikely be helpful for OCCT development: you will have to update PCH whenever you make a change in OCCT header. Not sure of current state of PCH support in Visual Studio, but when we experimented with PCH in the past it was not able to automatically recognize the need of updating PCH, which often led to incorrect builds after modifications. Thus I doubt if PCH can be really helpful for us OCCT developers. This is a reason why we have not started use of PCH yet.

However I see two use cases when PCH can be useful:

1. PCH for OCCT itself are useful if you need to just build OCCT from scratch, with no intent to modify it. This can be a case when you build it for use in some project; it would be also useful for certification testing to get results faster.

2. PCH for projects depending on OCCT. While it is up to a project to decide on using PCH, it could be useful if OCCT provides some synthetic headers collecting API headers by-toolkit or by-module, which can be used for easier generation of PCH in projects.

I have registered two issues for this, #27407 and #27409.

Andrey

Andrey BETENEV's picture

Hello,

To conclude this topic, precompiled headers are supported now (since 7.2.0 beta) by OCCT when building with CMake. To enable it, set CMake parameter BUILD_USE_PCH to TRUE.

This support is provided by third-party CMake module called Cotire (https://github.com/sakra/cotire, thanks to Etienne Rossignon for finding it!). It is non-intrusive, well documented, and quite easy to integrate -- just a couple CMake statements were sufficient to enable it in OCCT projects. The real problem was to get rid of multiple compiler errors due to clashes of precompiler macros defined in system headers with names like "min", "max", "Convex", "Opposite" etc. with normal code. Weird to see this stuff still present in modern systems!

The desired effect from use of precompiled headers is reduction of compile time. This effect is found to be rather moderate, 20-40%. Still can be useful in some circumstances. This comes on expense of 2-4 times more space needed for temporary files in the build folder.

Here are some measurements:

Compiler Build time, min Disk space, Mb
No PCH PCH Gain % No PCH PCH Expense
VS 2010 16 13 3 19% 1600 2750 1150
VS 2015 21 13 8 38% 950 2800 1850
GCC 5.2 23.5 19 4.5 19% 638 2660 2022

You are welcome to use the new feature and share your experience with it.

Andrey

QbProg's picture

Dear Andrey,
thank you very much for this feature!
I will take the time to test it and get back to you.

At a first glance, it seems to work good, but the precompiled header compilation time seems a little suspiciously low (MSVC2017). I don't know how cotire works though so I need to investigate :)

In my experience I have much bigger precompiled header file compilation times (using native VC method) but indeed if it's shorter is positive!

Alexander Malyshev's picture

Here are the results on my high-end desktop:

CPU: Core I7 6700k
MSVS: 2015 Community
Compiler: MSVS2015 default compiler
OCCT: 7.2.0 official release
Sources: Sources are placed on 7200 RPM HDD.

PCH: 8:14
NON-PCH: 14:54

So, the difference is very remarkable. This PCH-based version allowed me to compile 3 versions of OCCT (Release, Debug, and Release with debug information) in less than 30 minutes.

Alexander Malyshev's picture

Here are the results on low-end laptop:

CPU: AMD A10 5750m
MSVS: 2015 Community
Compiler: MSVS2015 default compiler
OCCT: 7.2.0 official release
Sources: Sources are placed on 5400 RPM HDD.

PCH: 00:51:55
NON-PCH: 01:38:03