{"id":1964,"date":"2012-06-15T10:43:46","date_gmt":"2012-06-14T23:43:46","guid":{"rendered":"http:\/\/blog.mozilla.org\/nnethercote\/?p=1964"},"modified":"2012-06-15T10:43:46","modified_gmt":"2012-06-14T23:43:46","slug":"memshrinks-1st-birthday","status":"publish","type":"post","link":"https:\/\/blog.mozilla.org\/nnethercote\/2012\/06\/15\/memshrinks-1st-birthday\/","title":{"rendered":"MemShrink&#8217;s 1st Birthday"},"content":{"rendered":"<p>A year ago today, the first meeting of the <a href=\"https:\/\/wiki.mozilla.org\/Performance\/MemShrink\">MemShrink project<\/a> took place.\u00a0 The project had been <a href=\"http:\/\/blog.mozilla.org\/nnethercote\/2011\/03\/10\/memshrink\/\">announced<\/a> almost three months earlier, but until that first meeting it was basically just me working on it and there wasn&#8217;t much momentum.\u00a0 So I now think of those three months as something of a gestation period, and the first meeting as the true birth of the project.<\/p>\n<p>So, happy birthday, MemShrink!\u00a0 I&#8217;ll take this opportunity to go over some of the accomplishments we&#8217;ve made in the past year.<\/p>\n<h3>Big Win #1: Better Javascript Heap Management<\/h3>\n<p>There have been two huge MemShrink improvements that stand out in my mind.\u00a0 The first one happened very early on, and it consisted of two related changes, both implemented by Gregor Wagner.<\/p>\n<p>In Firefox 4, the implementation of the JavaScript heap was totally overhauled.\u00a0 In particular, it was segregated into <a href=\"http:\/\/andreasgal.com\/2010\/10\/13\/compartments\/\">compartments<\/a>, each of which held (roughly speaking) the memory for a single domain.\u00a0 System compartments, i.e. those for JavaScript code that implements parts of Firefox (such as the UI), tend to be long-lived.\u00a0 In contrast, user compartments, i.e. those for JavaScript code in web pages, tend to be short-lived.\u00a0 But memory from both system and user compartments was being co-located in 1MB chunks.\u00a0 What tended to happen is that if you browsed for a long time and then closed many tabs, you&#8217;d end up with lots of 1MB chunks that were kept alive by a small amount of memory from system compartments.\u00a0 This is a form of fragmentation, and it prevented Firefox from releasing lots of memory back to the operating system that it should have been able to.<\/p>\n<p>Fortunately, Gregor came up with a simple fix:\u00a0 <a href=\"http:\/\/gregor-wagner.com\/?p=36\">don&#8217;t allow system and user compartments to share the same 1MB chunks<\/a>.\u00a0 To see just how effective this was, consider this visualization of the JavaScript heap after closing many tabs, without Gregor&#8217;s change.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone\" src=\"https:\/\/bug670594.bugzilla.mozilla.org\/attachment.cgi?id=545808\" alt=\"badly fragmented JavaScript heap\" width=\"781\" height=\"232\" \/><\/p>\n<p>Each horizontal line is a 1MB chunk, and each square is a 4KB arena.\u00a0 White squares are unused arenas, and coloured squares are in use.\u00a0 Arenas belong to a particular compartment all have the same colour;\u00a0 there are three compartments alive, all of which are system compartments.\u00a0 You can see that many 1MB chunks are kept alive by a small number of arenas.<\/p>\n<p>After Gregor&#8217;s change, in this scenario the heap ended up looking like this.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone\" src=\"https:\/\/bug670594.bugzilla.mozilla.org\/attachment.cgi?id=545809\" alt=\"non-fragmented JavaScript heap\" width=\"776\" height=\"80\" \/><\/p>\n<p><em>Much<\/em> better.<\/p>\n<p>Gregor&#8217;s second change related to garbage collection scheduling.\u00a0 In Firefox 4 the garbage collection heuristics were poorly tuned, and the garbage collector simply didn&#8217;t run frequently enough.\u00a0 Many people who left Firefox open for a while came back to find that JavaScript memory consumption had ballooned, and the machine was unusable due to paging, for seconds or minutes, until the garbage collector kicked in and paging finished.\u00a0 The fix was simple:\u00a0 <a href=\"http:\/\/gregor-wagner.com\/?p=27\">run the garbage collector occasionally, using a timer<\/a>.<\/p>\n<p>These two fixes of Gregor were the main reason why the first item in the <a href=\"http:\/\/www.mozilla.org\/en-US\/firefox\/7.0\/releasenotes\/\">Firefox 7 release note<\/a>s was &#8220;drastically improved <a href=\"http:\/\/hacks.mozilla.org\/2011\/09\/firefox-7-is-lean-and-fast\/\">memory handling<\/a> for certain use cases&#8221;.\u00a0 More specifically, <a href=\"http:\/\/blog.mozilla.org\/nnethercote\/2011\/08\/09\/firefox-7-is-lean-and-fast-2\/\">Firefox 7 used less memory than Firefox 6 (and 5 and 4): often 20% to 30% less, and sometimes as much as 50% less<\/a>.<\/p>\n<h3>Big Win #2: Fewer add-on Leaks<\/h3>\n<p>The second huge MemShrink improvement is much more recent.\u00a0 In fact it hasn&#8217;t even made it into a released version of Firefox yet.\u00a0 And the path towards it was much more circuitous.<\/p>\n<p>I <a href=\"http:\/\/blog.mozilla.org\/nnethercote\/2011\/05\/02\/a-better-aboutmemory-stage-1\/\">first<\/a> <a href=\"http:\/\/blog.mozilla.org\/nnethercote\/2011\/05\/12\/a-better-aboutmemory-stage-1-5\/\">revamped<\/a> <a href=\"http:\/\/blog.mozilla.org\/nnethercote\/2011\/05\/23\/a-better-aboutmemory-stage-1-75\/\">about:memory<\/a> in May of last year, and those changes made it into Firefox 6. This started giving us insight into Firefox&#8217;s memory consumption, but it wasn&#8217;t until I broke up the reporting of JS memory consumption on a <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=661474\">per-compartment basis<\/a> that it really started to make a difference.\u00a0 (This change made it into Firefox 7, another reason why that release was so good from a memory consumption point of view.)<\/p>\n<p>Per-compartment reporters made some <a href=\"http:\/\/blog.mozilla.org\/nnethercote\/2011\/06\/21\/you-make-what-you-measure\/\">blatant inefficiencies<\/a> obvious, which were quickly fixed.\u00a0 More importantly, people quickly noticed that sometimes compartments were present for sites that had been closed long ago.\u00a0 This is a kind of memory leak that became known as a <a href=\"http:\/\/blog.mozilla.org\/nnethercote\/2011\/07\/20\/zombie-compartments-recognize-and-report-them-stop-the-screaming\/\">zombie compartment<\/a>, and hunting them became a popular enough sport that\u00a0 <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=668871\">more than 100 zombie compartment bug reports<\/a> have been filed.<\/p>\n<p>Some of the zombie compartments were due to defects in Firefox itself, and these were generally fixed fairly quickly.\u00a0 However, it soon became clear that the majority of them are <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=700547\">due to add-ons<\/a>.\u00a0 It&#8217;s <a href=\"https:\/\/developer.mozilla.org\/en\/Extensions\/Common_causes_of_zombie_compartments_in_extensions\">quite easy<\/a> to unintentionally create zombie compartments in add-ons.\u00a0 In the <a href=\"http:\/\/blog.mozilla.org\/nnethercote\/2012\/02\/17\/the-mcafee-site-advisor-add-on-has-an-appalling-memory-leak\/\">worst case<\/a>, add-ons could leak the compartment of every single site visited.<\/p>\n<p>This led to some lively discussion about how best to handle these leaks, because they are defects in third-party code that is largely out of Mozilla&#8217;s control, and yet they make Firefox look bad.\u00a0 Fortunately, this discussion became mostly moot when Kyle Huey took advantage of an 8,000 mile trip from home to implement a crazy idea he&#8217;d had six months earlier &#8212;\u00a0 when a tab is closed, simply <a href=\"http:\/\/blog.kylehuey.com\/post\/21892343371\/fixing-the-memory-leak\">cut the references from other compartments<\/a> that would keep the compartment of the tab&#8217;s page alive.\u00a0 This turns out to <a href=\"http:\/\/blog.mozilla.org\/nnethercote\/2012\/05\/07\/update-on-leaky-add-ons\/\">work tremendously well<\/a> and prevents most of the cases where add-ons can create zombie compartments.\u00a0 This change is scheduled to ship in Firefox 15, which is due for release in late August, and should more or less fix what I six months ago ranked as the <a href=\"http:\/\/blog.mozilla.org\/nnethercote\/2012\/01\/25\/memshrink-progress-week-32\/\">single worst problem<\/a> affecting Firefox&#8217;s memory consumption.<\/p>\n<h3>The Key Tool: Memory Reporters and About:memory<\/h3>\n<p>I mentioned about:memory above.\u00a0 It&#8217;s worth discussing in more detail, because it&#8217;s the single most important tool we&#8217;ve created, and has driven a lot of the MemShrink improvements.<\/p>\n<p>Let&#8217;s look at about:memory as it was in Firefox 6, which was released about 10 months ago.<a href=\"http:\/\/blog.mozilla.org\/nnethercote\/files\/2012\/06\/aboutmemory-ff6.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-2004\" title=\"aboutmemory-ff6\" src=\"http:\/\/blog.mozilla.org\/nnethercote\/files\/2012\/06\/aboutmemory-ff6.png\" alt=\"about:memory screenshot from Firefox 6\" width=\"632\" height=\"733\" srcset=\"https:\/\/blog.mozilla.org\/nnethercote\/files\/2012\/06\/aboutmemory-ff6.png 632w, https:\/\/blog.mozilla.org\/nnethercote\/files\/2012\/06\/aboutmemory-ff6-258x300.png 258w\" sizes=\"(max-width: 632px) 100vw, 632px\" \/><\/a><\/p>\n<p>Even these early versions had several key properties.<\/p>\n<ul>\n<li>about:memory doesn&#8217;t need a special build to run;\u00a0 it works even in released versions.<\/li>\n<li>It is trivially easy to use &#8212; you just type &#8220;about:memory&#8221; in the address bar.<\/li>\n<li>Because it&#8217;s all text you can cut and paste the output, and unlike many web pages it is carefully constructed so that it reproduces beautifully when you do so.\u00a0 No screenshots are necessary.<\/li>\n<\/ul>\n<p>These properties massively expand the number of people who are able to detect and report problems relating to memory consumption.\u00a0 <em>Any<\/em> Firefox user can potentially do it;\u00a0 if the user doesn&#8217;t already know how, they can be taught in 10 seconds.<\/p>\n<p>Having said that, this old version is almost laughably primitive compared to what we have now.\u00a0 First, let&#8217;s consider the state of the memory reporting infrastructure, which about:memory completely relies on, as it was at that time.<\/p>\n<ul>\n<li>There were a fixed number of measurements, which meant there were no individual measurements for variable-numbered entities such as compartments, window objects, or SQLite connections.\u00a0 Such measurements were only possible once I added support for <a href=\"https:\/\/developer.mozilla.org\/en\/XPCOM_Interface_Reference\/nsIMemoryMultiReporter\">memory multi-reporters<\/a>.\u00a0 We now have dozens of measurements per variable-numbered entity, and thousands of measurements in total.<\/li>\n<li>Even once per-compartment reporters were added, we still didn&#8217;t have much insight into the memory consumption of the JavaScript code used by Firefox itself (and its add-ons).\u00a0 But <a href=\"http:\/\/bholley.wordpress.com\/2012\/05\/04\/at-long-last-compartment-per-global\/\">compartment-per-global<\/a> landed recently and gave us much finer-grained measurements, which (a) gives us some idea of how much memory is being used by JavaScript-based add-ons, and (b) gets us very close to being able to <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=687724\">report memory consumption for each tab<\/a>.\u00a0 Users have been requesting both of these things for <em>years<\/em>.<\/li>\n<li>Early memory reporters had lots of defects that caused them to report incorrect numbers, but these were obvious only when the numbers were ridiculously large or negative (both of which happened on occasion).\u00a0 The first of two major improvements in correctness came about as we learned how to structure memory reporters to avoid common defects.\u00a0 In particular, <a href=\"https:\/\/wiki.mozilla.org\/Memory_Reporting#Making_Measurements\">it&#8217;s best to write reporters that are traversal-based rather than counter-based, and to measure heap blocks with <code>malloc_usable_size<\/code> rather than computing the sizes<\/a>.\u00a0 Reporters that use <code>malloc_usable_size<\/code> also measure slop bytes, which are caused by the heap allocator rounding up allocation requests and can account for 5&#8211;10% of the heap.\u00a0 Early reporters didn&#8217;t have these characteristics, but most of them have been converted now.<\/li>\n<li>Reporters with these characteristics are doubly-virtuous, because they also integrate well with <a href=\"https:\/\/wiki.mozilla.org\/Performance\/MemShrink\/DMD\">DMD<\/a>, a tool I wrote that dynamically checks memory reports.\u00a0 DMD provided the second major improvement in memory reporter correctness, because it identifies heap blocks that are counted twice, which is a mistake that&#8217;s easy to make.<\/li>\n<li>DMD also identifies unreported heap blocks, and was crucial in getting the &#8220;heap-unclassified&#8221; number down.\u00a0 In the example above it was 68.82%(!), whereas now it&#8217;s typically around 15%, which is low enough that people have mostly stopped complaining about it.\u00a0 Prior to DMD, identifying this &#8220;dark matter&#8221; was much harder and less systematic.<\/li>\n<li>The only tree shown in the above example is &#8220;explicit&#8221;.\u00a0 On Linux, Justin Lebar added code to summarize the information in the <code>\/proc\/&lt;pid&gt;\/smaps<\/code> file in &#8220;size&#8221;, &#8220;rss&#8221;, &#8220;pss&#8221; and &#8220;swap&#8221; trees.<\/li>\n<li>The reporters back then could only report byte measurements.\u00a0 They can now report unitless counts and percentages, both of which are useful.<\/li>\n<\/ul>\n<p>Now consider the about:memory page itself, as it was back then.<\/p>\n<ul>\n<li>Insignificant measurements were simply omitted, and you had to reload in verbose mode to see them (and the measurements would be re-taken when that happened, potentially losing any interesting measurements).\u00a0 Now it is possible to expand and collapse arbitrary parts of the trees on the fly.<\/li>\n<li>The &#8220;Other Measurements&#8221; section contained a flat list of measurements.\u00a0 Trees are now possible, which makes that section more flexible and easier to understand.<\/li>\n<li>about:memory&#8217;s has been carefully streamlined to consume as little memory as possible, so that it doesn&#8217;t perturb what it&#8217;s measuring.\u00a0 This is really important now that we report so many measurements.<\/li>\n<li>about:memory now has a companion page, about:compartments, that just lists compartments (and <a href=\"http:\/\/jlebar.com\/2012\/5\/30\/A_ghost_story.html\">ghost windows<\/a>).\u00a0 about:compartments shares a lot of code with about:memory, and it is better than about:memory for certain tasks such as spotting zombie compartments.<\/li>\n<\/ul>\n<p>All this stuff is important because <a href=\"http:\/\/blog.mozilla.org\/nnethercote\/2011\/06\/21\/you-make-what-you-measure\/\">you make what you measure<\/a>.\u00a0 Just about every time we&#8217;ve started measuring some new thing, we&#8217;ve found and fixed problems as a result.<\/p>\n<h3>Smaller Things<\/h3>\n<p>The following smaller accomplishments were also made in the past year.<\/p>\n<ul>\n<li>John Schoenick used the <a href=\"https:\/\/wiki.mozilla.org\/Auto-tools\/Automation_Development\/Projects\/Endurance_Tests\">MozMill endurance tests<\/a> to build <a href=\"https:\/\/areweslimyet.com\/\">areweslimyet.com<\/a>, which helps identify regressions in memory consumption.<\/li>\n<li>I removed a lot of unnecessary memory waste caused by &#8220;<a href=\"http:\/\/blog.mozilla.org\/nnethercote\/2011\/08\/05\/clownshoes-available-in-sizes-2101-and-up\/\">clownshoes<\/a>&#8221; allocations.<\/li>\n<li>Olli Pettay wrote <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=726346\">about:cc<\/a> and Jan Honza Odvarko wrote <a href=\"http:\/\/www.softwareishard.com\/blog\/planet-mozilla\/hunting-zombie-memory-leaks-in-firefox\/\">about:ccdump<\/a>.\u00a0 These closely related tools have been used to find various cycle collector leaks.<\/li>\n<li>I wrote <a href=\"https:\/\/wiki.mozilla.org\/Performance\/MemShrink#Meeting_Minutes.2C_Progress_Reports_and_Presentations\">41 progress reports<\/a>.\u00a0 I had\/have two goals with these:\u00a0 to keep interested people informed of what it happening, and to provide evidence that Mozilla actually <em>does<\/em> care about memory consumption in Firefox.<\/li>\n<\/ul>\n<p>This is only the tip of the iceberg, though.\u00a0 As I am writing this, there have been 314 MemShrink-tagged bugs marked FIXED in Bugzilla.\u00a0 In comparison, there are only 221 MemShrink-tagged bugs currently open.\u00a0 Breaking them down by priority we get the following.<\/p>\n<ul>\n<li>P1: 52 fixed, 25 open<\/li>\n<li>P2: 135 fixed, 88 open<\/li>\n<li>P3: 53 fixed, 106 open<\/li>\n<li>Unprioritized: 74 fixed, 2 open<\/li>\n<\/ul>\n<p>Over 75 people were responsible for these fixes.\u00a0 I give many thanks to all those people, plus everybody who contributed in any other way to fixes, such as bug reporters and patch reviewers.\u00a0 And I&#8217;d like to give extra thanks to the MemShrink regulars:\u00a0 Justin Lebar, Kyle Huey, Andrew McCreight, Johnny Stenback, and Jet Villegas.<\/p>\n<h3>What&#8217;s Next?<\/h3>\n<p>There&#8217;s no real secret to MemShrink.\u00a0 So far it&#8217;s basically been a long, steady grind, gradually improving tools, fixing leaks, slimming down data structures, and responding to user&#8217;s problems.\u00a0 There are no plans to change that, and we&#8217;ll continue our recently-lowered pace of fortnightly meetings for the foreseeable future.\u00a0 And if we&#8217;re lucky, I might be writing a report on MemShrink&#8217;s second birthday a year from now!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A year ago today, the first meeting of the MemShrink project took place.\u00a0 The project had been announced almost three months earlier, but until that first meeting it was basically just me working on it and there wasn&#8217;t much momentum.\u00a0 So I now think of those three months as something of a gestation period, and [&hellip;]<\/p>\n","protected":false},"author":139,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4550,4554,30,4544,4546],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/posts\/1964"}],"collection":[{"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/users\/139"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/comments?post=1964"}],"version-history":[{"count":0,"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/posts\/1964\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/media?parent=1964"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/categories?post=1964"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/tags?post=1964"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}