🔒 Locked
C++ Templates = Code Overhead?
Advertisement
Original Post
The compiler does indeed have to generate seperate code for each type that you use to instantiate a template, but as far as I know it should be able to optimize down things that you dont use. For example, if you instantiate a template class with five types, but only ever call one method, you will get at least five versions of that method (plus constructors, destructors, and so on.
Quote:
Original post by Zoomby
Hi, I wonder:
Do C++ templates cause code "overhead" in the executable? Is it right that the compiler has to generate duplicate code for each type I use with a template class for example? Or do "modern" compilers optimize it in some way?
Bye
Chris
Yes and no. The way templates work, the code is duplicated for each type you use. However, it only instantiates the code you actually use. (If you define a class template with 5 functions, and only use one of them, the four remaining member functions won't be compiled)
So it *is* possibly to get some impressive code bloat by overusing templates, but generally, it's not really a problem, since the compiler strips out unused code pretty aggressively.
Also, for PC applications at least, a few hundred KB of code more or less usually doesn't really matter.
You mean code bloat and yes for each different type given which has no (partial) specialization the duplicate code is generated for this type.
However once a template instantiation occurs this definition is reused. Also one can force an instantiation for a particular type.
This should not be of any concern to yourself unless you're making heavy use of template metaprogramming otherwise this should not deter you from using templates.
There are various techniques to reducing codebloat caused by templates, partial specializations, using lazy template instantiation techniques but as i said before i really doubt this be of any concern as long as you're not too naive with templates.
However once a template instantiation occurs this definition is reused. Also one can force an instantiation for a particular type.
This should not be of any concern to yourself unless you're making heavy use of template metaprogramming otherwise this should not deter you from using templates.
There are various techniques to reducing codebloat caused by templates, partial specializations, using lazy template instantiation techniques but as i said before i really doubt this be of any concern as long as you're not too naive with templates.
Quote:
Original post by Zoomby
Do C++ templates cause code "overhead" in the executable? Is it right that the compiler has to generate duplicate code for each type I use with a template class for example?
Correct.
Is it really overhead, however? If you were not using templates, what would your code look like? You'd have different methods/types, one for each underlying type you would be overloading for, causing equal code duplication. The upside with templates is that you only have to write the code once (barring specializations), whereas without them you'd have to write it N times, once for each underlying type.
Considered in that fashion, it is not overhead at all. Happy hacking!
Quote:
Original post by Zoomby
Hi, I wonder:
Do C++ templates cause code "overhead" in the executable? Is it right that the compiler has to generate duplicate code for each type I use with a template class for example? Or do "modern" compilers optimize it in some way?
Yes, the compiler will usually generate a different instance of a templated function for each type. It's not overhead: if the compiler didn't generate the code, you would have to write it anyways.
There are two things that help reduce the perceived code bloat that results from using templates.
First off, you can use partial template specialization to reduce the amount of generated code. This is detailed in "The C Programming Language" by Bjarne Stroustrup (a must read, by the way). SO, for example, if you're designing a templated container and you provide partial specializations for pointer types, you basically end up with one set of generated function specialized on void*, just like you would if you were writing old-fashioned reinvented-wheel code in C, but with the advantages of type safety and generally more efficient code due to the inlining advantages inherent in templated code.
Second, unlike other techniques (object-oriented C, rooted inheritance heirarchies a la Java) the compiler will emit code for templated functions only if they're used. In other words, you can write 1000 member functions for a templated class, but only the three functions you use in your code will be emitted. With the proper use of templates you can actually generate less code than alternative, more traditional means to the same end.
--smw
I have seen evidence lately that if the types instantiated are similiar enough, VS2005 will use the same instanciation. I.e. if you instanciate a template function with <int>, and with <long> (where these are both 32-bits) then it ends up calling the same version of the function for these two.
Depending on what the function actually does with the type provided, I wouldn't be surprised if it could do the same thing in other cases too.
Depending on what the function actually does with the type provided, I wouldn't be surprised if it could do the same thing in other cases too.
Quote:
I have seen evidence lately that if the types instantiated are similiar enough, VS2005 will use the same instanciation. I.e. if you instanciate a template function with <int>, and with <long> (where these are both 32-bits) then it ends up calling the same version of the function for these two.
It can, in fact, do this for just about any set of functions for which the generated code is identical. This is an optimization known as "identical COMDAT folding" in MSVC++, and it is technically a linker option, I think (other toolchains can do it too, although they may use different nomenclature).
Quote:
Original post by Anonymous Poster
and namespaces? Do they cause overhead in code execution speed?
namespaces in their normal use have absolutely zero overhead on generated opcodes. Obviously if you are using typeid() and doing string compares against qualified names, then the strings are longer and the matching takes longer, but normal operation of a C and C++ compiler is all resolevd at compile and link time except the known case of virtual functions ... so calling:
ObsurdCompany::Orangizing::Too::Many::Levels::Deep::NiceClass c1 = new ObsurdCompany::Orangizing::Too::Many::Levels::Deep::niceClass();
is identical to:
NiceClass c1 = new NiceClass; // int he global namespace
when it comes to generated codem, opcodes, speed, etc. (readability here is of course horrible ... but that would be fixed with a simple using statement)
The ONLY normal cost of longer names and nesting / namespaces in C++ is that the symbol names and RTTI info get longer in the compiled files (expecially in debug files) - because of course a linker has to be able to recognize the different versions of similar functions in different namespaces. But once the linker is done with its job, the namespace has no requirement to even exist in the binary anymore ... only exported symbols actually need to keep their metadata.
Quote:
Original post by jpetrie Quote:
I have seen evidence lately that if the types instantiated are similiar enough, VS2005 will use the same instanciation. I.e. if you instanciate a template function with <int>, and with <long> (where these are both 32-bits) then it ends up calling the same version of the function for these two.
It can, in fact, do this for just about any set of functions for which the generated code is identical. This is an optimization known as "identical COMDAT folding" in MSVC++, and it is technically a linker option, I think (other toolchains can do it too, although they may use different nomenclature).
And let me tell you, that so scared us when we first ran into it while debugging a strange problem. "why are we in a class that is completely unrelated to our pointer?!?!"
Two "get and return an integer" accessors had been determined to be idential, so only one was generated, and we thought we had virtual pointer corruption. :)
Quote:Oh yeah, I remember seeing that happen once before too! (Stepping into a function and it appears to step into a similiar function in an unrelated class). It was very unexpected at the time![totally]
Original post by NotAYakk Quote:
Original post by jpetrie Quote:
I have seen evidence lately that if the types instantiated are similiar enough, VS2005 will use the same instanciation. I.e. if you instanciate a template function with <int>, and with <long> (where these are both 32-bits) then it ends up calling the same version of the function for these two.
It can, in fact, do this for just about any set of functions for which the generated code is identical. This is an optimization known as "identical COMDAT folding" in MSVC++, and it is technically a linker option, I think (other toolchains can do it too, although they may use different nomenclature).
And let me tell you, that so scared us when we first ran into it while debugging a strange problem. "why are we in a class that is completely unrelated to our pointer?!?!"
Two "get and return an integer" accessors had been determined to be idential, so only one was generated, and we thought we had virtual pointer corruption. :)
The problem was, the debugger & debugging symbols assumed that each line of ASM has a definate source code location.
Once you have something like comdat folding, this doesn't work. You need to know all of the lines of code that map to your current disassembly location.
The UI for this is not something I can solve off the cuff. :)
Once you have something like comdat folding, this doesn't work. You need to know all of the lines of code that map to your current disassembly location.
The UI for this is not something I can solve off the cuff. :)
Quote:
Original post by Anonymous Poster
WRT gcc, the idea is however somewhat beyond COMDAT folding alone:
http://gcc.gnu.org/ml/gcc/2006-09/threads.html#00246
http://gcc.gnu.org/ml/gcc/2006-09/msg00246.html
Hmm, care to summarize? I read a handful of random posts, and most of them just seemed to be people saying "There's nothing to be gained, and it'd be almost impossible to implement properly"
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement