{"id":246,"date":"2009-09-22T15:01:54","date_gmt":"2009-09-22T22:01:54","guid":{"rendered":"http:\/\/gameangst.com\/?p=246"},"modified":"2009-09-22T15:02:59","modified_gmt":"2009-09-22T22:02:59","slug":"minimizing-code-bloat-redundant-template-instantiation","status":"publish","type":"post","link":"http:\/\/gameangst.com\/?p=246","title":{"rendered":"Minimizing Code Bloat: Redundant Template Instantiation"},"content":{"rendered":"<p><em>This article is a continuation of <a href=\"http:\/\/gameangst.com\/?p=46\">Minimizing Code Bloat for Faster Builds and Smaller Executables<\/a>.<\/em><\/p>\n<p>The last item on my list of code bloat causes is redundant template instantiation. \u00a0Template functions have a lot in common with inline functions. \u00a0Like inline functions, template functions are instantiated into the object file of every translation unit in which they are used. \u00a0Also like inline functions, template functions generate weak symbols which are merged silently by the linker. \u00a0Redundant template instantiations won&#8217;t increase your executable size, but they can contribute significantly to your build times.<\/p>\n<p>Consider a commonly used class like <em>std::string<\/em>. \u00a0The std::string class is actually a template class defined as:<\/p>\n<p><div class=\"dean_ch\" style=\"white-space: nowrap;\"><span class=\"kw4\">typedef<\/span> basic_string&lt;char, char_traits&lt;char&gt;, allocator&lt;char&gt; &gt; string;<\/div>\n<\/p>\n<p>In an engine that uses std::strings, some members like std::string::assign may be referenced in nearly every translation unit. \u00a0Even engines that eschew the use of std::string may unknowingly be instantiating a lot of std::string code because it is so pervasive in the standard library. \u00a0Looking at a symbol dump from one version of Despair Engine, I see over 1600 instances of dozens of functions from std::string. \u00a0That&#8217;s right, in every full build we compile most of std::string 1600 times, optimize the code 1600 times, write it into .obj files 1600 times, copy it into .lib files 1600 times, read it into the linker 1600 times, and then throw 1599 identical copies away! \u00a0All told I think it is less than 10 megabytes of code and accounts for only a couple percent of our build times, but still, it&#8217;s a lot to pay for a wrapper around a char*.<\/p>\n<p>Don&#8217;t think that these sorts of problems are confined to the standard library. \u00a0Any template class that is widely used can produce a lot of code bloat from redundant instantiations. \u00a0The question is, what do you do about it?<\/p>\n<p>One option is to convert template code into non template code. \u00a0If you never instantiate basic_string with anything other than a single set of parameters, is it really worth being a template class? \u00a0The same question could be asked of a templatized math library. \u00a0Does matrix&lt;T&gt; need to be a template class when all you ever use is matrix&lt;float&gt;?<\/p>\n<p>Although removing template code is always an option, it isn&#8217;t always a good one. \u00a0Template code may be expensive, but it is also really handy. \u00a0If you have a templatized math library, chances are that while 99% of the instantiations are matrix&lt;float&gt;, somewhere in your engine or tools you have an instantiation of matrix&lt;double&gt;. \u00a0Similarly, amid all those instantiations of basic_string&lt;char&gt;, maybe there&#8217;s a basic_string&lt;wchar_t&gt; or two hanging out.<\/p>\n<p>Luckily there is a way to prevent redundant template instantiations without changing the code. \u00a0That is through the use of explicit template instantiation declarations. \u00a0Explicit instantiation declarations aren&#8217;t technically part of the C++ standard, but they&#8217;re supported by <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/by56e477.aspx\">MSVC<\/a> and <a href=\"http:\/\/gcc.gnu.org\/onlinedocs\/gcc\/Template-Instantiation.html#Template-Instantiation\">gcc<\/a> and they&#8217;re included in the C++09 draft standard, so they&#8217;re a safe bet to use. \u00a0What explicit instantiation declarations do is allow you to prevent the compiler from instantiating a particular template in the current translation unit. \u00a0They look just like explicit instantiation definitions, but they&#8217;re preceded by the extern keyword. \u00a0For example, the explicit instantiation declaration of basic_string&lt;char&gt; looks like this:<\/p>\n<p><div class=\"dean_ch\" style=\"white-space: nowrap;\"><span class=\"kw4\">extern<\/span> <span class=\"kw2\">template<\/span> <span class=\"kw2\">class<\/span> basic_string&lt;char&gt;;<\/div>\n<\/p>\n<p>You can add this declaration to a root header in your application and rebuild, and, unless you&#8217;ve missed a translation unit, you&#8217;ll encounter linker errors for missing basic_string&lt;char&gt; symbols. \u00a0Once you&#8217;ve removed all the basic_string&lt;char&gt; instantiations from your engine, the next thing to do is to add one back so the linker has all the code it needs to put together a complete executable. \u00a0That&#8217;s where\u00a0explicit instantiation definitions come in.<\/p>\n<p>Explicit instantiation definitions are the counterpart to explicit instantiation declarations. \u00a0They tell the compiler to fully instantiate a particular template even if it is otherwise unused in the current translation unit. \u00a0Here&#8217;s an example of how you can use the two concepts together to prevent redundant instantiations of basic_string.<\/p>\n<blockquote>\n<div class=\"dean_ch\" style=\"white-space: nowrap;\"><span class=\"co1\">\/\/ in string_instantiation.h<\/span><br \/>\n<span class=\"co2\">#ifdef DS_EXTERN_TEMPLATE_INSTANTIATION<\/span><br \/>\n<span class=\"kw2\">namespace<\/span> std<br \/>\n<span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw4\">extern<\/span> <span class=\"kw2\">template<\/span> <span class=\"kw2\">class<\/span> basic_string&lt;char&gt;;<br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"co2\">#endif<\/span><\/p>\n<p><span class=\"co1\">\/\/ in string_instantiation.cpp<\/span><br \/>\n<span class=\"co2\">#ifdef DS_EXTERN_TEMPLATE_INSTANTIATION<\/span><br \/>\n<span class=\"co2\">#undef DS_EXTERN_TEMPLATE_INSTANTIATION<\/span><\/p>\n<p><span class=\"co2\">#include &quot;string_instantiation.h&quot;<\/span><\/p>\n<p><span class=\"kw2\">namespace<\/span> std<br \/>\n<span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw2\">template<\/span> <span class=\"kw2\">class<\/span> basic_string&lt;char&gt;<br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"co2\">#endif \/\/ DS_EXTERN_TEMPLATE_INSTANTIATION<\/span><\/div>\n<\/blockquote>\n<p>The DS_EXTERN_TEMPLATE_INSTANTIATION <em>#define<\/em> in the above code serves two purposes. \u00a0First it allows us to disable explicit template instantiation for compilers that don&#8217;t support it, and second it allows us to work around a common bug in compilers that do support it. \u00a0Although the standard states that an explicit instantiation definition may follow an explicit instantiation declaration within a translation unit, many compilers don&#8217;t like it and won&#8217;t allow an explicit instantiation definition to override a preceding explicit instantiation declaration.<\/p>\n<p>There is one dark fact about explicit template instantiation that you should know before applying it in your own codebase. \u00a0Although explicit template instantiation effectively turns template code into non template code from the perspective of code bloat, it doesn&#8217;t really help much with classes like std::string. \u00a0The syntax for out-of-line template class function definitions is so cumbersome that many programmers prefer to implement all their template class members entirely within the class declaration. \u00a0That&#8217;s what has happened with Microsoft&#8217;s STL implementation. \u00a0Unfortunately what that does is implicitly make every member function in a template class an inline function. \u00a0Of course most of the member functions are so large that they&#8217;ll never be inlined, but it doesn&#8217;t matter from the perspective of the compiler.<\/p>\n<p>The explicit template declaration of basic_string&lt;char&gt; prevents the compiler from instantiating its members as template functions, but it doesn&#8217;t prevent it from instantiating them as inline functions! \u00a0The basic_string class goes from a classic example of code bloat due to redundant template instantiation to a classic example of code bloat due to <a href=\"http:\/\/gameangst.com\/?p=224\">incorrect inlining<\/a>! \u00a0You can&#8217;t win!<\/p>\n<p>In your own code, at least, you can fix the incorrect inlining problem right after you fix the redundant instantiation problem. \u00a0Just move the template class member functions out of line and they&#8217;ll disappear from your symbol dumps.<\/p>\n<p>And that&#8217;s everything I know about code bloat in a voluminous 6 part series. \u00a0Perhaps what I should be writing about is blog bloat. \u00a0All that&#8217;s left is to <a href=\"http:\/\/gameangst.com\/?p=320\">post some code<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This article is a continuation of Minimizing Code Bloat for Faster Builds and Smaller Executables. The last item on my list of code bloat causes is redundant template instantiation. \u00a0Template functions have a lot in common with inline functions. \u00a0Like inline functions, template functions are instantiated into the object file of every translation unit in [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[8,14,7],"_links":{"self":[{"href":"http:\/\/gameangst.com\/index.php?rest_route=\/wp\/v2\/posts\/246"}],"collection":[{"href":"http:\/\/gameangst.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/gameangst.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/gameangst.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/gameangst.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=246"}],"version-history":[{"count":12,"href":"http:\/\/gameangst.com\/index.php?rest_route=\/wp\/v2\/posts\/246\/revisions"}],"predecessor-version":[{"id":309,"href":"http:\/\/gameangst.com\/index.php?rest_route=\/wp\/v2\/posts\/246\/revisions\/309"}],"wp:attachment":[{"href":"http:\/\/gameangst.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=246"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/gameangst.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=246"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/gameangst.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=246"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}