{"id":226,"date":"2013-10-05T17:27:11","date_gmt":"2013-10-05T21:27:11","guid":{"rendered":"http:\/\/blog.mozilla.org\/nfroyd\/?p=226"},"modified":"2013-10-05T17:27:11","modified_gmt":"2013-10-05T21:27:11","slug":"faster-c-builds","status":"publish","type":"post","link":"https:\/\/blog.mozilla.org\/nfroyd\/2013\/10\/05\/faster-c-builds\/","title":{"rendered":"faster c++ builds by building bigger groups of code"},"content":{"rendered":"<p>There have been a lot of spectacular build changes going into the tree lately; my personal builds have gotten about 20% faster, which is no mean feat.\u00a0 One smaller change that I&#8217;ve implemented in the last couple weeks is compiling the DOM bindings and the IPDL IPC code in what we&#8217;re been calling &#8220;unity&#8221; mode.<\/p>\n<p>The idea behind unity mode is to compile a C++ file that #includes your actual C++ source files.\u00a0 What&#8217;s the win from this?<\/p>\n<ul>\n<li>Fewer compiler processes launched.\u00a0 This is a good thing on Windows, where processes are expensive; it&#8217;s even a good thing on platforms where process creation is faster.<\/li>\n<li>Less disk I\/O.\u00a0 The best case is if the original C++ source files include a lot of the same files.\u00a0 Compiling the single C++ file then includes those headers only once, rather than once per original C++ source file.<\/li>\n<li>Smaller debug information.\u00a0 On Linux, at least, every Gecko object file compiled with debug information is going to include information about basic types like uint32_t, FILE, and so forth.\u00a0 Compiling several files together means that you cut down on multiple definitions of things in the debug information, which is good.<\/li>\n<li>Better optimization.\u00a0 The compiler is seeing more source code at once, which means it has more information to make decisions about things like inlining.\u00a0 This often leads to things not getting inlined (perhaps because the compiler can see that a function is called several times across several different files rather than one time in each of several source files).<\/li>\n<\/ul>\n<p>It&#8217;s a little like link-time code optimization, except that your compiler doesn&#8217;t need to support LTO.\u00a0 SQLite, in-tree and otherwise, already provides an option to compile everything as one big source file and claims ~5% speedup on benchmarks.<\/p>\n<p>The concrete wins are that the DOM bindings compile roughly 5x faster, the IPC IPDL bindings compile roughly 2x faster, libxul got 100k+ smaller on Android, and that the Windows PGO memory required went down by over 4%.\u00a0 (The PGO memory decrease was just from building DOM bindings in unity mode; the effect from the IPC code appears to have been negligible.)\u00a0 The downside is that incremental builds when WebIDL or IPDL files are modified get slightly slower.\u00a0 We tried to minimize this effect by compiling files in groups of 16, which appeared to provide the best balance between full builds and incremental builds.<\/p>\n<p><a href=\"http:\/\/mxr.mozilla.org\/mozilla-central\/search?string=_add_unified_build_rules\">The code is in moz.build<\/a> and it&#8217;s not specific to the DOM bindings or IPC IPDL code; it will work on any collection of C++ source files, modulo issues with headers being included in unexpected places.\u00a0 The wins are probably highest on generated code, but I&#8217;d certainly be interested in hearing what happens if other bits of the tree are compiled in unity mode.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There have been a lot of spectacular build changes going into the tree lately; my personal builds have gotten about 20% faster, which is no mean feat.\u00a0 One smaller change that I&#8217;ve implemented in the last couple weeks is compiling the DOM bindings and the IPDL IPC code in what we&#8217;re been calling &#8220;unity&#8221; mode. [&hellip;]<\/p>\n","protected":false},"author":320,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.mozilla.org\/nfroyd\/wp-json\/wp\/v2\/posts\/226"}],"collection":[{"href":"https:\/\/blog.mozilla.org\/nfroyd\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mozilla.org\/nfroyd\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/nfroyd\/wp-json\/wp\/v2\/users\/320"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/nfroyd\/wp-json\/wp\/v2\/comments?post=226"}],"version-history":[{"count":0,"href":"https:\/\/blog.mozilla.org\/nfroyd\/wp-json\/wp\/v2\/posts\/226\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.mozilla.org\/nfroyd\/wp-json\/wp\/v2\/media?parent=226"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mozilla.org\/nfroyd\/wp-json\/wp\/v2\/categories?post=226"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mozilla.org\/nfroyd\/wp-json\/wp\/v2\/tags?post=226"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}