17

In a large project we have a lot of classes (thousands), and for each of them a special smart pointer type is defined using typedef. This smart pointer type is a template class. When I compile with "gcc -Q" I see that a lot of time is spent compiling these smart pointers for each class. That is I see smartptr<class1>::methods, then smartptr<class2>::methods... smartptr<class2000>::methods scrolling on the screen as gcc processes them.

Is there a trick to speedup this process? These classes are all the same from the smartptr point of view, no enable_if tricks, etc.

What I am trying right now:

  • maybe make a non-template base class with few common methods
  • use extern template class to reduce link symbols (and instantiation time? not sure yet)

But all of the above is not a complete solution. I wonder if there's another way to optimize compilation time, a trick to make gcc know that e.g. if it parsed smartptr once it could apply the same knowledge over and over again when seeing other specializations, because the generate code is the same.

Yes I know that it is not quite the same of course... But that's just a crazy idea.

Or maybe there're other tricks that I'm not aware of, that could speed up compilation. (Just to give the idea of what I'm talking, we could optimize another template by eliminating its static member data instantiation, which greatly reduced compilation time. This was not obvious at all.)

queen3
  • 15,333
  • 8
  • 64
  • 119
  • 4
    Does this help ? http://stackoverflow.com/questions/7182359/template-instantiation-details-of-gcc-and-ms-compilers – brian beuning Dec 27 '12 at 20:18
  • Not quite sure - yet, but it surely deserves upvote. – queen3 Dec 27 '12 at 20:29
  • 1
    So I recall that std vector used to reuse void * implementation for T* -- basically casting was all the T* needed to do. That trick might be worth exploring. – Yakk - Adam Nevraumont Dec 27 '12 at 20:58
  • Depending on how smart and how compatible your pointer is, `#define smartptr std::shared_ptr` could help. Inlining your methods would reduce link/instantiate time as well. – Olaf Dietsche Dec 27 '12 at 21:11
  • @Yakk: A smartptr needs more information about T than a vector of pointers (e.g. for deleting objects) because it (typically) owns the object it points to. This trick would only work if it was an option to derive all 2000 classes from a shared base class, forcing the destructor to be virtual (or alternatively introducing a virtual abstract method release() which calls delete this). Then you could make some of the smartptr methods independent of T (i.e. move them into some base_smartptr class) – Stacker Dec 27 '12 at 21:21
  • Addref does not need to delete, as an example. So that can be factored out... – Yakk - Adam Nevraumont Dec 27 '12 at 21:32
  • are your classes `class1` through `class2000` perhaps instantiations of a single `class` template? – TemplateRex Dec 27 '12 at 21:55
  • Related question: http://stackoverflow.com/questions/2827422/how-to-reduce-compile-time-with-c-templates (It's probably not a duplicate, because this one here asks for GCC tricks and gives specific examples.) – jogojapan Dec 28 '12 at 02:06
  • _When I compile with "gcc -Q" I see that a lot of time is spent compiling these smart pointers for each class_ - doesn't say anything about time. What is `template instantiation` time and percentage as reported by `-Q` switch? – Maxim Egorushkin Jan 11 '13 at 09:42
  • Template instantiation is... template instantiation. If this number is high then extern templates may help. E.g. if it is 5% and we optimize it, compilation will be 5% faster. Sadly not in my case. – queen3 Jan 11 '13 at 20:22

2 Answers2

1

Not specifically GCC, but I think that the idea of deriving smartptr from a non-template base class sounds like a good bet. A smart pointer is a good candidate for this approach because much of the code which is being repeatedly generated doesn't care that the pointer isn't void*. (I would shift as much code over as you can so that the class template does little more than cast to and from void* where necessary.)

Also, if you have thousands of classes which are relying heavily on smartptr, then nipping the problem in the bud this way should be considered first. Only when that fails would I move on to smartptr's client code (at which point, techniques for avoiding general header bloat become worth considering).

As for extern template declarations, I have no experience of these but it sounds like you would need to add an extern declaration per typedef. Notably, the opposite effect of forcing complete instantiation is performed like this:

template class smartptr<MyClass>;

I would double check that this line doesn't accompany any of your typedefs!

John McFarlane
  • 5,528
  • 4
  • 34
  • 38
0

Precompiled header

If your code changes are not in the header this might actually help with reducing the compilation time. (src)

user1055604
  • 1,624
  • 11
  • 28
  • Probably not a very wise answer, templates are only in header files so any changes to the templates will thrash the PCH. And with templates one wants to optimize slow building of C++ files that is due to template instantiation taking place. Again, PCH doesn't help here (it may save some time spent in parsing the templates but not in the instantiation, which seems to be the bottleneck here). So the way to go is to optimize the template code itself, especially if the templates are instantiated many times or if they are recursive (computing something at compile time / working on typelists). – the swine Jan 08 '13 at 11:16
  • That is actually a complicated question as it depends on compiler specifics (most likely a template member function is instantiated when called). So if you assume that the template is used in a code that is in the header file then yes. On the other hand, you shouldn't really have any code in a header file (except declarations and inline functions), unless it is code of another template. So in a code following this convention no. – the swine Jan 09 '13 at 10:45