views:

973

answers:

8

C++ templates have been a blessing in my everyday work because of its power. But one cannot ignore the (very very very very long) compilation time that results from the heavy use of templates (hello meta-programming and Boost libraries). I have read and tried quite a lot of possibilities to manually reorganize and modify template code to make it compile as fast as possible.

Now I am wondering if there are any c++ compilers that try and minimize the needed time to interpret template classes. I might be wrong, but i feel that the compilers i do know have only added template interpretation to their previous versions.

My questions are :

  • Is c++ template code so difficult to interpret that there is not much to optimize ? (i highly doubt that)
  • Are there c++ compilers that truly optimize "c++ templates" interpretation ?
  • Are there projects to develop a new generation of c++ compilers that would optimize this ?
  • If you were to participate in such a project, what would your guidelines be ?
+1  A: 

It's not going to be the answer you want but Walter Bright was the main developer of the first native C++ compiler, and an optimized c++ complier. After all that he wrote his own programming language called D. It's basically an improvement on C++ and copes with templates better.

I do not know of any c++ compiler that it optimized for template use.

James Brooks
IIRC someone did a 50 production grammar with Boost::Spirit (a meta programing parser generator) and it took 17 hours to compile. I have a 250 production grammar that compiles using a D equivalent in 7 *minutes*
BCS
Now that is the kind of gain i am expecting ! But i can't change every existing code to D language !
Benoît
A: 

I think templates themselves are not so complex in themselves. We'll see when concepts are introduced in c++0x, etc., but at the moment, templates are just (almost) as macros, so the real problem is not that if you have optimized c++ compilers for templates. The problem is that templates do generate such a huge amount of code when compiling, that make compilation slower.

Diego Sevilla
Can you elaborate on what you believe makes compilation slower ? I personally use templates as a way to isolate the development of classes in my projects. If there were only one project, I could do the exact same thing without any templates. But there are many projects hence many templates !
Benoît
Benoît, compilation **is** slower with templates. Note that when you use, say, vector<int> and call some functions on it, the compiler takes the templated code and compiles it for the int type. If you use, say, vector<string>, the same. However normally compilation speed should normally be a...
Diego Sevilla
... second concern, as many times, with templates you're able to develop a cleaner solution to a problem, or even solve things that you cannot do without templates. So summing up: templates make compiling slower, but they are a key abstraction in C++.
Diego Sevilla
Believe me, i know how much slower compilation can get when using templates. In my first comment, what i was trying to say is that i was *not* using multiple instanciations of each template class. All the contrary ! I essentially use policy classes as template arguments. I am looking for reasons...
Benoît
...why "template c++" compiling takes much longer, even though i am *not* in the case you described. By the way, i know what templates bring. I just want it all, compilation speed and template power. And i strongly feel it can be achieved. Hence my question.
Benoît
I see. In the specific case you only use a specialization of the template, compiling should not be slower as if you had implemented it with plain code. Note, however, that compiling two programs mean then compiling twice the code, instead of compiling once and linking it the second time.
Diego Sevilla
Yes, excessive use of templates (Hmm, for varying definitions of 'excessive') do make compilation slower, but the compiler is attempting to optimize the *result* of compilation, and make the final executable faster.
Arafangion
+1  A: 

Try Incredibuild. It dramatically cuts down compile/build time.

This product basically enables Visual C++ to build across multiple machines in your organization by taking advantage of idle cycles. I've used Incredibuild on huge projects (500 kloc) with lots of template code and got good speedup in build times.

m-sharp
+9  A: 

This really isn't an answer to your question. It's more of a side observation.

I'm not an C++ language lawyer either , and so I could be way off base with some of the details.

But, the rough idea should be correct.

The main reason that C++ compilers take such a long time to compile template meta-programs is because of the way template meta-programs are specified.

They aren't specified directly as code that you want the compiler to run at compile time. Take the example of computing the length of a type list.

If you could write code like this:

compile_time size_t GetLength(TypeList * pTypeList)
{
    return DoGetLength(pTypeList, 0);
}

compile_time size_t DoGetLength(TypeList * pTypeList, size_t currentLength)
{
    if (pTypeList)
    {
        return DoGetLength(pTypeList->Next, ++currentLength);
    }
    else
    {
         return currentLength;
    }
}

That was some how compiled separately from the code where it was used, and was exposed to the language via some syntax, then the compiler would be able to execute it very quickly.

It would just be a simple recursive function call.

It's possible to design language that allows those sorts of things. Most of the ones that do this (like lisp) are dynamically typed, but it is possible to do with static typing. However, it's not likely to ever be something you would see implemented in C++.

The problem in C++, however, is that the code is written like:

template <typename First,  typename Second>
struct TypeList
{
    typedef First Head;
    typedef Second Tail;
};

template <>
struct ListSize<NullType>
{
    enum {  size = 0  };
};

template <typename Head, typename Tail>
struct ListSize<TypeList<Head, Tail> >
{
    enum {  size = 1 + ListSize<Tail>::size  };
};

In order for the compiler to "execute" the meta-program it has to:

  1. Construct a dependency graph for the initial values of the "size" enum value
  2. Construct a template type for each edge in the graph
  3. Bind all the symbols referenced by each constructed template type
  4. Topologically sort the dependency graph
  5. Traverse the graph and evaluate the constants

This is much more expensive than just simply running a O(N) recursive algorithm.

The worst case would be something like O(N * M * L), with N equal to the length of the list, M being the level of scope nesting , and L being the number of symbols in each scope.

My advice would be to minimize the amount of C++ template meta-programming that you use.

Scott Wisniewski
+1. I like your example. It's exactly what i have in mind. Template meta-programming is "just" scripting with the compiler as an interpreter. Though it cannot be processed in O(N), I don't believe we would get anywhere close to your worst case scenario...
Benoît
+12  A: 
Johannes Schaub - litb
+6  A: 

The main problem with templates is the following:

You cannot (usually) separate the definition of your templates class from its declaration and put it inside a .cpp file.

The consequence: Everyting is in header files. Whenever you include a header you include a whole lot of code that would in normal circumstances be nicely separated into .cpp files and compiled separately. Every compile unit includes a few headers, and so, with templates, every compile unit contains a lot of code, or almost all of your project, via the included headers.

If that is your problem, then look here, at a related question:

It got a very good answer, which does solve that problem.

Basically, it involves instantiating the templates that you need once, and compile them into an object file. Later you can link against it, and you don't have to include that code everywhere. It's separated into a compiled object file. Note: That makes sense only if you use only just a few instantiated types of your templates (say, you only need MyType<int> and MyType<double> in your program).

It uses the g++ flag -fno-implicit-templates.

That technique is so helpful that I think it should be incorporated into the C++ faq: [35.12] Why can't I separate the definition of my templates class from it's declaration and put it inside a .cpp file?

Of course you are right. Everything is in header files. But that does not mean it can't be in separated header files. I work everyday with template classes separated in two sets of header files : declaration and implementation...
Benoît
...Why not add another one for forward declaration ? Anyway, actual cpp files contain both implementation and instantiated template parameters. It does work very well, but unfortunately, it's not helping very much as far as compilation speed is concerned.
Benoît
Re your first comment: Just putting template declarations and implementations into separate header files won't help compilation speed. You still have to include both for each compilation unit, if you don't use the trick described in my answer.
+1  A: 

The gold linker can help decrease link-time by about 5 times, which can reduce the overall compile time. Its particularly helpful since linking can't be parallelized in the same way that compilation can.

(Not a direct answer, but hopefully this is helpful).

Paul Biggar
+1  A: 

It seems that g++ 4.5 has made tremendous progress dealing with templates. Here are the two unavoidable changes.

  • "When printing the name of a class template specialization, G++ will now omit any template arguments which come from default template arguments." That could be considered a subtle modification, but it will have an enormous impact on development with c++ templates (ever heard of unreadable error messages... ? No more !)

  • "Compilation time for code that uses templates should now scale linearly with the number of instantiations rather than quadratically." This is going to severely undermine compilation-time arguments against the use of C++ templates.

See on the gnu site for complete information

Actually, i am already wondering whether there still are issues with c++ templates ! Mmm, yes, there are, but let's focus on the bright side for now !

Benoît