Saturday 17 September 2016

Templates and Build Times

Quick iteration is probably one of the most important recipes for successful games development. And nothing kills coder iteration like long build times. For this reason some studios out-rightly ban the use of templates or generally frown on them since they can be a severe compile bottleneck.

However the real reason templates can cripple compile times is actually a problem at the core of C++ headers parsing. Template code traditionally lives entirely in the header file, even though it doesn't need to! In fact templates are one of the few places where the use of inline (.inl) files actually makes sense to me. By separating the template implementation into an inline file, you can keep the dependent header-files light, while only source (.cpp) files where the template implementations are explicitly used need to include the .inl file. I'd say as a general best practice, you should never include inline files in a header file anyway; else what's the point of the modularity/code-separation?

Code Example


foo_template.h
template<typename T> class foo_template
{
void DoSomething();
};

foo_template.inl
template<typename T>
inline foo_template<T>::DoSomething() { printf("doing something y'all"); }

foo.h
#include foo_template.h
class Foo
{
foo_template<T> mFoo;
public:
void DoSomething();
};

foo.cpp
#include foo_template.inl
void Foo::DoSomething() { mFoo.DoSomething(); }


Avoiding templates means forgoing a hugely powerful C++ feature just because it's little understood. Used well, they can yield much simpler & cleaner code - which leads to less bugs & saves overall iteration time, without any noticeable hit on your compile times. Furthermore if you already know all the types that need to be generated by your templates, you can forward-define them all in one .cpp file - your compiler won't even notice.

If you really want to reduce compile times, forward declarations are your friend, use them in your headers instead of #includes and watch your build times drop. I would highly recommend Niklas's Header Hero. With this and a couple days of architectural restructuring, I was able to get a project that took roughly 12 mins to rebuild, down to 7 mins. I was aiming for 4 mins and probably would have gotten close; but for something that was unscheduled, it was beginning to take too long & involved changing infinitely more code files mid-project.

You should ideally integrate a culture of minimal build times right from the initial stages of a project, not midway through. I think this is a much better culture to promote rather than a ban on templates, as
from my findings, none of the hotspots I fixed were template headers. Just lots of careless header dependencies & tight coupling - which is another good reason to prefer containment over inheritance, but I'll save that rant for another day :)

No comments:

Post a Comment