{"id":224,"date":"2009-09-21T08:19:35","date_gmt":"2009-09-21T15:19:35","guid":{"rendered":"http:\/\/gameangst.com\/?p=224"},"modified":"2009-09-21T08:20:32","modified_gmt":"2009-09-21T15:20:32","slug":"minimizing-code-bloat-incorrect-inlining","status":"publish","type":"post","link":"http:\/\/gameangst.com\/?p=224","title":{"rendered":"Minimizing Code Bloat: Incorrect Inlining"},"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>Earlier I talked about <a href=\"http:\/\/gameangst.com\/?p=212\">excessive inlining<\/a> as a common cause of code bloat. \u00a0Excessive inlining is when code that shouldn&#8217;t be inlined is. \u00a0Today I&#8217;m going to look at a related problem, code that is declared as inlined but never will be.<\/p>\n<p>Any function whose address is taken for storage in a function pointer or a virtual function table can never fully be inlined. \u00a0Even for a function that can legally be inlined, the compiler has ultimate authority over whether or not it will be. \u00a0If a function is large the compiler will generally forgo inlining it because the performance benefits of removing the function call overhead don&#8217;t justify the increase in executable size. \u00a0That&#8217;s all well and good, but it still poses a problem.<\/p>\n<p>C++ compilers work by dividing programs into something called <a href=\"http:\/\/stackoverflow.com\/questions\/1106149\/what-is-a-translation-unit-in-c\">translation units<\/a>. \u00a0A translation unit is a single cpp file and all the headers it includes. \u00a0The compiler turns these translation units into object files and ultimately the linker combines the contents of all the object files into an executable. \u00a0The important thing to note is that every function visible to the compiler in a translation unit must be compiled as part of that unit. \u00a0In the case of a function that is declared inline, the compiler will generate a compiled instantiation of the function in every cpp file that uses it. \u00a0The various redundant instantiations are marked as <a href=\"http:\/\/en.wikipedia.org\/wiki\/Weak_symbol\">weak\u00a0symbols<\/a> so the linker knows that multiple copies are expected and that it can pick any one of them for use in the final executable.<\/p>\n<p>Knowing this, you can see how wasteful functions that are incorrectly marked as inline can be. \u00a0Large functions are less likely to be inlined, are more likely to take a long time to compile, and consequently can be murder on your build times.<\/p>\n<p>By this point you should have a pretty good idea of how to detect incorrect inlining. \u00a0The same technique I proposed for measuring excessive inlining and the compile-time cost of template overspecialization works equally well for detecting incorrect inlining. \u00a0Dump the symbols from all your object files with <em>DumpBin \/headers<\/em> and look for large functions with lots of redundant instantiations.<\/p>\n<p>One of the most interesting (and insidious!) sources of incorrect inlining is code that you don&#8217;t write at all. \u00a0Consider this apparently harmless class definition:<\/p>\n<blockquote>\n<div class=\"dean_ch\" style=\"white-space: nowrap;\"><span class=\"kw2\">class<\/span> DataBox<br \/>\n<span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; PhysicsData &nbsp; &nbsp; m_physics;<br \/>\n&nbsp; &nbsp; AIData &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;m_ai;<br \/>\n&nbsp; &nbsp; GraphicsData &nbsp; &nbsp;m_graphics;<br \/>\n&nbsp; &nbsp; AnimationData &nbsp; m_animation;<br \/>\n&nbsp; &nbsp; UIData &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;m_ui;<br \/>\n&nbsp; &nbsp; ScriptData &nbsp; &nbsp; &nbsp;m_script;<br \/>\n&nbsp; &nbsp; NetworkData &nbsp; &nbsp; m_network;<br \/>\n<span class=\"br0\">&#125;<\/span>;<\/div>\n<\/blockquote>\n<p>This class is potentially a major contributor to code bloat from incorrect inlining. \u00a0If you&#8217;re scratching your head and wondering how a class with no functions can contribute to code bloat, take a look at the next listing to see this class the way the compiler sees it.<\/p>\n<blockquote>\n<div class=\"dean_ch\" style=\"white-space: nowrap;\"><span class=\"kw2\">class<\/span> DataBox<br \/>\n<span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; PhysicsData &nbsp; &nbsp; m_physics;<br \/>\n&nbsp; &nbsp; AIData &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;m_ai;<br \/>\n&nbsp; &nbsp; GraphicsData &nbsp; &nbsp;m_graphics;<br \/>\n&nbsp; &nbsp; AnimationData &nbsp; m_animation;<br \/>\n&nbsp; &nbsp; UIData &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;m_ui;<br \/>\n&nbsp; &nbsp; ScriptData &nbsp; &nbsp; &nbsp;m_script;<br \/>\n&nbsp; &nbsp; NetworkData &nbsp; &nbsp; m_network;<\/p>\n<p>&nbsp; &nbsp; <span class=\"co1\">\/\/ Not legal C++. &nbsp;This is for illustration purposes only.<\/span><br \/>\n&nbsp; &nbsp; DataBox<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; m_physics.<span class=\"me1\">PhysicsData<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; m_ai.<span class=\"me1\">AIData<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; m_graphics.<span class=\"me1\">GraphicsData<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; m_animation.<span class=\"me1\">AnimationData<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; m_ui.<span class=\"me1\">UIData<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; m_script.<span class=\"me1\">ScriptData<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; m_network.<span class=\"me1\">NetworkData<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>;<br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><\/p>\n<p>&nbsp; &nbsp; ~DataBox<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; m_network.~NetworkData<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; m_script.~ScriptData<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; m_ui.~UIData<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; m_animation.~AnimationData<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; m_graphics.~GraphicsData<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; m_ai.~AIData<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; m_physics.~PhysicsData<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span>;<br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span>;<\/div>\n<\/blockquote>\n<p>In C++ every class has a constructor, a destructor, a copy constructor, and an assignment operator. \u00a0If you don&#8217;t provide these functions the compiler will, and it must do so inline. \u00a0Of course good compilers will only instantiate inline functions when they are actually used, so most classes never have their default copy constructor or assignment operators generated, but unless you&#8217;re doing something dangerously clever in your codebase, every class has a destructor instantiated at least once.<\/p>\n<p>If you notice default (also sometimes called automatic) methods showing up in the top slots of your redundant function hotlist, the fix is counterintuitive but also really simple. \u00a0Just provide an empty, non-inline implementation in place of the default one. \u00a0Providing empty, non-inline implementations of default methods for nontrivial classes can sometimes help your build times in other ways. \u00a0If you use a lot of smart pointers in your code, the default destructor of a class holding smart pointers may be the only thing preventing you from replacing the #includes of the headers for the classes stored in smart pointers with forward declarations of those classes. \u00a0In other words, inline functions create header dependencies, and inline default methods are no exception.<\/p>\n<p>Speaking of <a href=\"http:\/\/en.wikipedia.org\/wiki\/Smart_pointer\">smart pointers<\/a>, as great as they are, code bloat is one of their unfortunate costs. \u00a0As I mentioned above, good compilers only instantiate inline code when it is actually used. \u00a0Reference counting smart pointers allow for distributed ownership of objects, which can be a powerful and convenient design freedom. \u00a0However, if responsibility for destroying objects is widely distributed through your code, so is responsibility for instantiating object destructors. \u00a0An engine with rigorously defined ownership hierarchies will have few inline destructor instantiations whereas an engine with sloppily defined ownership hierarchies will have many. \u00a0So if you use smart pointers, use them responsibly! \u00a0Pass by reference and reference count only when necessary. \u00a0Unnecessary reference counting isn&#8217;t just inefficient at run time, it is inefficient at compile time too!<\/p>\n<p>If all this sounds like a major pain in the neck, I suggest you give up now and implement <a href=\"http:\/\/buffered.io\/posts\/the-magic-of-unity-builds\/\">unity builds<\/a>. \u00a0They circumvent all these redundant instantiation issues so they&#8217;re fantastic at optimizing build times in codebases with poor structure. \u00a0On the other hand, if you&#8217;re still enjoying this trek through compile land, join me next time for a discussion of <a href=\"http:\/\/gameangst.com\/?p=246\">redundant template instantiation<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This article is a continuation of Minimizing Code Bloat for Faster Builds and Smaller Executables. Earlier I talked about excessive inlining as a common cause of code bloat. \u00a0Excessive inlining is when code that shouldn&#8217;t be inlined is. \u00a0Today I&#8217;m going to look at a related problem, code that is declared as inlined but never [&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\/224"}],"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=224"}],"version-history":[{"count":17,"href":"http:\/\/gameangst.com\/index.php?rest_route=\/wp\/v2\/posts\/224\/revisions"}],"predecessor-version":[{"id":669,"href":"http:\/\/gameangst.com\/index.php?rest_route=\/wp\/v2\/posts\/224\/revisions\/669"}],"wp:attachment":[{"href":"http:\/\/gameangst.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=224"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/gameangst.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=224"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/gameangst.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=224"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}