27

I have seen a couple of questions on how to detect unnecessary #include files in a C++ project. This question has often intrigued me, but I have never found a satisfactory answer.

If there are some header files included which, are not being used in a c++ project, is that an overhead? I understand that it means that before compilation the contents of all the header files would be copied into the included source files and that would result in a lot of unnecessary compilation.

How far does this kind of overhead spread to the compiled object files and binaries?

Aren't compilers able to do some optimizations to make sure that this kind of overhead is not transferred to the resulting object files and binaries ?

Considering the fact, that I probably know nothing about compiler optimization, I still want to ask this, in case there is an answer.

As a programmer who uses a wide variety of c++ libraries for his work, what kind of programming practices should I follow to keep avoiding such overheads ? Is making myself intimately familiar with each library's working the only way out ?

Ujjwal Aryan
  • 3,827
  • 3
  • 20
  • 31
  • It depends on what's in the include files. Structure declarations don't produce any runtime overhead. External variable declarations do. – Barmar May 05 '15 at 20:22
  • Circular dependencies aside, having unneccessary includes increases your compilation time, which for large projects already takes a long time (order of magnitude - hours) – Cory Kramer May 05 '15 at 20:24
  • @Cyber If it already takes hours, another 30 seconds here or there isn't going to make much difference. – Barmar May 05 '15 at 20:25
  • 4
    @Barmar *Declaring* a variable (i.e. informing the compiler that a variable of this name is defined elsewhere) has a run time cost? Really? How? –  May 05 '15 at 20:25
  • @delnan To initialize the variable. – Barmar May 05 '15 at 20:25
  • 1
    @Barmar It depends what dependency you include (how far upstream). You can turn a 10 minute project rebuild far downstream into a 1.5 hour rebuild just by introducing a dependency that is far upstream (depending on your build/rebuild settings and what you changed) – Cory Kramer May 05 '15 at 20:26
  • 3
    @Barmar When the variable is defined in another TU, it's initialized there, not where you declare its existence. –  May 05 '15 at 20:26
  • Thus, if I can summarize, as long as header files contain only declarations, there should be no extra code generation and no overhead. However, am I right in saying that if someone has also defined functions in header files, then surely there would be a big overhead ? – Ujjwal Aryan May 05 '15 at 20:31
  • @UjjwalAryan: Functions defined in header files will have an unbelievably tiny runtime overhead if they're used, or no runtime overhead if not used. Though compiling and linking takes longer in either case. – Mooing Duck May 05 '15 at 20:35
  • 1
    I think you should take out the C tag. C and C++ are quite different with that. As said in some comment, C++ headers even tend to define some symbols that are not used bit still might not be optimized out. And also compilation times are much more an issue for C++ than for C. So really the answers for both languages will probably be quite different. – Jens Gustedt May 05 '15 at 20:50

4 Answers4

26

It does not affect the performance of the binary or even the contents of the binary file, for almost all headers. Declarations generate no code at all, inline/static/anonymous-namespace definitions are optimized away if they aren't used, and no header should include externally visible definitions (that breaks if the header is included by more than one translation unit).

As @T.C. points out, the exception are internally visible static objects with nontrivial constructors. iostream does this, for example. The program must behave as if the constructor is called, and the compiler usually doesn't have enough information to optimize the constructor away.

It does, however, affect how long compilation takes and how many files will be recompiled when a header is changed. For large projects, this is enough incentive to care about unnecessary includes.

  • There is a few exceptions. Function definitions in headers are duplicated in every resulting binary that includes them, and larger binaries take longer to load, and duplicated functions interfere with the instruction cache, resulting in minescule performance penalties. – Mooing Duck May 05 '15 at 20:32
  • @MooingDuck The linker can usually throw them out, no? – T.C. May 05 '15 at 20:33
  • @T.C.: It throws out duplicates of a function _in object files as they're linked into a single binary_. However, it can't throw out functions used in several DLLs or EXEs. – Mooing Duck May 05 '15 at 20:34
  • @MooingDuck I thought I addressed that in the answer? The assumption here is that the include is unnecessary, i.e. the functions are not used and can thus be stripped by the compiler. Are you talking about externally visible definitions? Those clash with the ODR (and the equivalent rule in C) so there can't be duplicates of them. –  May 05 '15 at 20:35
  • I was thinking of internally visible functions that _are_ used. You're right that unused functions add no size or runtime overhead. – Mooing Duck May 05 '15 at 20:37
  • 2
    The header can *define* objects with internal linkage, in which case you'll pay for their initialization. (Including ``, for instance, must act as if it defines a `ios_base::Init` object with static storage duration.) – T.C. May 05 '15 at 20:37
  • @delnan No, `` must act as if it defined an instance of that class. (The idea is to ensure that anything after the include can use the standard stream objects.) Usually it's just implemented as a `static ios_base::Init __some_reserved_name;`. – T.C. May 05 '15 at 20:44
  • @T.C. Yes, I crossed some wires and was thinking of a reference to an externally defined static object, which is of course nonsense. –  May 05 '15 at 20:47
6

Besides the obviously longer compile times, there might be other issues. The most important one IMHO is dependencies to external libraries. You don't want your program to depend on more libraries then necessary.

You also then need to install those libraries in every system you want to the program to build on. This can become a nightmare, especially when the next programmer needs to install some database client library although the program never uses a database.

Also, especially library headers often tend to define macros. Sometimes those macros have very generic names which will break you code or which are incompatible with other library headers you might actually need.

Daniel Frey
  • 55,810
  • 13
  • 122
  • 180
  • Can you really have a *dependency* on an external library if you're not actually using anything from it? For example, if you `#include` it but never reference any of its contents? – Mr. Llama May 05 '15 at 22:07
  • @Mr.Llama You are probably thinking about the linker throwing away anything and not even forcing you to link with the actual library. But you need to install the library so that the header is found, otherwise your code will not compile. Legally, it might also already count as a dependency license-wise. So you already depend on the library, even if only to build your project. – Daniel Frey May 05 '15 at 22:58
3

Of course any #include is an overhead. The compiler needs to parse that file.

So avoid them. Use forward declarations where ever possible.

It will speed up compilation. See Scott Myers book on the subject

Ed Heal
  • 59,252
  • 17
  • 87
  • 127
1

The simple answer is YES its an overhead as far as the compilation is concerned but for runtime it is merely going to create any difference. Reason being lets say you add #include <iostream> (just for example) and assume that you are not using any of its function then g++ 4.5.2 has some additional 18,560 lines of code to process(compilation). But as far as the runtime overhead is concerned I hardly think that it creates a performance issue.

You can also refer Are unused includes harmful in C/C++? where I really liked this point made by David Young

Any singletons declared as external in a header and defined in a source file will be included in your program. This obviously increases memory usage and possibly contributes to a performance overhead by causing one to access their page file more often (not much of a problem now, as singletons are usually small-to-medium in size and because most people I know have 6+ GB of RAM).

Community
  • 1
  • 1
Rahul Tripathi
  • 168,305
  • 31
  • 280
  • 331
  • 1
    Funny you used `#include ` as an example, because including that header does incur a small overhead at run time. – T.C. May 05 '15 at 20:35
  • @T.C.:- Indeed, but I was just trying to make a point. May be I could have added `#include ` which has approx 74k lines. – Rahul Tripathi May 05 '15 at 20:36