Include guard optimisation


This page grew from a discussion on comp.lang.c++.moderated about the most efficient way of #including header files in a C or C++ program. Normally, each header file should only be #included once. In a moderately sized project where header files #include other header files it can be difficult to keep to this rule without some form of automated help. A common idiom is to put "include guards" around the contents of the header file being included. E.g.

File "myheader.hpp"

#ifndef MYHEADER_HPP
#define MYHEADER_HPP

// Contents of include file go here

#endif

Thus, even if the file is #included multiple times, its contents will only be processed once. This is known as an internal include guard, because the guard is entirely internal to the header file.

One problem with this method is that if the compiler takes a naive approach, it will still have to open the file multiple times to check for the internal include guard. In a large project this could cause increased compile times. This point is made by John Lakos in his book "Large Scale C++ Software Design", and is used as an argument to support the following idiom:

File "myheader2.hpp"

#ifndef MYHEADER_HPP
#include "myheader.hpp"
#endif

// Rest of header file goes here

The guard symbol (MYHEADER_HPP) is still defined and checked internally, however by checking the guard symbol externally as well, the compiler might avoid having to open the header file at all. It is suggested that this external check is only done when a header file is included from other header files - when a file is #included from a source file the external check can be omitted. The internal guard is used to guarantee correctness, the external guard increases the speed of compilation. The cost involved is that of putting the check everywhere a header file is #included in another header file, and spelling the name of the guard symbol correctly.

It turns out that some compilers will allow us to have our cake and eat it by implementing the "include guard optimisation".

What is the include guard optimisation?

The include guard optimisation is when a compiler recognises the internal include guard idiom described above and takes steps to avoid opening the file multiple times. The compiler can look at an include file, strip out comments and white space and work out if the whole of the file is within the include guards. If it is, it stores the filename and include guard condition in a map. The next time the compiler is asked to include the file, it can check the include guard condition and make the decision whether to skip the file or #include it without needing to open the file.

Since not all compilers implement this optimisation I have put together a benchmark to allow the optimisation to be checked for. There is also a results page available to allow you to look up a given compiler.

How does the benchmark work?

The benchmark uses two header files - one with an internal include guard and one without:

guard.h noguard.h
#ifndef GUARD_H
#define GUARD_H
extern int i;
#endif
extern int i;

Three C source files then #include these header files multiple times:

In order to get times that are large enough to measure easily, the number of includes needs to be large (several thousand). Sample test files and the software to generate them are available from the downloads section.


Download the software to run the test yourself

Results


If you have any feedback on the benchmark or the contents of these pages please email me

This page last modified 12 August 2009