[gameprogrammer] Blog post on improving compile and link speeds of C++ projects
- From: Kevin Jenkins <gameprogrammer@xxxxxxxxxx>
- To: gameprogrammer@xxxxxxxxxxxxx
- Date: Tue, 11 Apr 2006 08:49:27 -0700
In case anyone is interested, I wrote in my blog some techniques to
improve compile and link speeds of C++ projects
http://www.rakkar.org/blog/?p=69
At work we have a very large codebase, in the millions of lines of code.
Nobody understands all the code, and half the people who wrote it aren’t
at the company anymore. So a lot of my time is spent experimentally -
tracing through code to figure out how it works, or making small changes
to fix unforeseen bugs. The problem is this requires a lot of
recompiling small changes. Unfortunately, the code is designed in such a
way that sometimes small changes result in the recompilation of hundreds
of files.
I spend half my day not programming, nor thinking, but waiting for the
compiler. This is by an order of magnitude the biggest hindrance towards
my accomplishing anything meaningful. A single line of code change can
take 15 minutes when you consider the time to build, the time to link,
the time to regain my lost attention, and the time to do it all again
for my second instance of Visual Studio (for network programming).
Fortunately, I’ve learned a few things as the author of RakNet that can
help with compile and link times. While they may be obvious to
experienced programmers, even experienced programmers don’t consistently
follow them so they are worth reviewing.
1. It’s bad to include header files in your cpp files. It’s
exponentially bad to include header files in other header files
.cpp files increase the time to compile your project linearly. For
example, if my cpp file includes “blah.h” then every time “blah.h”
changes, then I have to recompile all cpp files that include that.
That’s bad - but still far better than header files, which increase your
total compile time exponentially. If files C.h and D.h include B.h, and
B.h includes A.h, then anytime A.h changes we have to compile 4 header
files - A.h, B.h, C.h, and D.h. But it’s not just 4 header files - we
are now also rebuilding any cpp file that includes any of those header
files.
2. Avoid, as much as possible, putting code in header files
Code is likely to change. Class definitions are much less likely to
change. Furthermore, code in a cpp file is only included in that one
place - that cpp. Code in a header file is included everywhere that
header file is included. If you put code in a header file, that means
that you are likely to change that header file and you are including the
same code all over your program meaning it gets recompiled every time.
3. Split up your header into independent classes/structs/enums as much
as possible.
It’s a hassle to add header files to a project. Oftentimes, when two
kinds of interfaces, such as an enumeration and a structure, are both
used with a class, it’s tempting to put both in the same header file.
Supermarket.h
enum Fruits {APPLE, ORANGE, GRAPE};
class Supermarket {Fruits GetType(Fruit *fruit);};
There are two problems with this. First, enumerations are likely to
change. If we later add POMEGRANATE then every class that includes this
needs to be recompiled. Secondly, every class that cares about Fruits
now has to also include Supermarket, and vice-versa, resulting in
unnecessary compiles.
4. If your class has complex or templated types in the header, think
about exposing an interface for that class.
Interfaces can be a hassle since you now have to maintain two copies of
your class definition, rather than one. However, in some cases they can
vastly cut down on compile times. Consider the following:
Database.h
#include "ComplexTemplatedList.h"
class Database
{
Rec* GetRecord();
ComplexTemplatedList recordsList;
};
DatabaseInterface.h
class Database
{
virtual Rec* GetRecord()=0;
};
In the second version, we got rid of all the implementation code yet
every class that needs Database can still use it and now compile almost
instantly.
5. Inside header files, include pointers to other classes rather than
the classes themselves
CompileSlow.h
#include "CompositeClass.h"
class MyClass
{
CompositeClass a;
}
CompileFast.h
class CompositeClass;
class MyClass
{
CompositeClass *a;
}
Sorry if my last point is obvious, but it’s the easiest to do so is
worth pointing out.
In conclusion, a few minutes of trouble today can save hours over the
life of the project, not just for you but every other programmer that
has to do builds.
---------------------
To unsubscribe go to http://gameprogrammer.com/mailinglist.html
- Follow-Ups:
- References:
- [gameprogrammer] Re: Level of detail rendering
- From: Bob Pendleton
- [gameprogrammer] Re: Level of detail rendering
- From: Charlie Lobo
Other related posts:
- » [gameprogrammer] Blog post on improving compile and link speeds of C++ projects
- » [gameprogrammer] Re: Blog post on improving compile and link speeds of C++ projects
--------------------- To unsubscribe go to http://gameprogrammer.com/mailinglist.html
- [gameprogrammer] Re: Level of detail rendering
- From: Bob Pendleton
- [gameprogrammer] Re: Level of detail rendering
- From: Charlie Lobo