{"id":1668,"date":"2012-01-25T17:19:19","date_gmt":"2012-01-25T06:19:19","guid":{"rendered":"http:\/\/blog.mozilla.org\/nnethercote\/?p=1668"},"modified":"2012-01-25T17:19:19","modified_gmt":"2012-01-25T06:19:19","slug":"memshrink-progress-week-32","status":"publish","type":"post","link":"https:\/\/blog.mozilla.org\/nnethercote\/2012\/01\/25\/memshrink-progress-week-32\/","title":{"rendered":"MemShrink progress, week 32"},"content":{"rendered":"<p>There wasn&#8217;t much MemShrink activity this week in terms of bugs fixed, just <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=718100\">bug 718100<\/a> and <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=720359\">bug 720359<\/a>.\u00a0 So I&#8217;m going to take the opportunity this week to talk about the bigger picture.<\/p>\n<h3>Bug Counts<\/h3>\n<p>As a prelude, here are this week&#8217;s bug counts.<\/p>\n<ul>\n<li>P1: 20 (-4\/+0)<\/li>\n<li>P2: 131 (-3\/+3)<\/li>\n<li>P3: 74 (-2\/+7)<\/li>\n<li>Unprioritized: 4 (-3\/+4)<\/li>\n<\/ul>\n<p>The drop in P1s was just due to bug re-classification;\u00a0 in particular, three bugs relating to long cycle collector pauses were un-MemShrink&#8217;d because they are more about responsiveness, and they are being tracked by <a href=\"https:\/\/wiki.mozilla.org\/Performance\/Snappy\">Project Snappy<\/a>.<\/p>\n<h3>The Big Ticket Items<\/h3>\n<p>David Mandelin asked me today what where the big ticket items for MemShrink.\u00a0 I&#8217;d been looking a lot at the MemShrink:P1 list recently (which is why some were re-classified) and so I was able to break it down into six main areas that cover most of the P1s and various P2s.\u00a0 I&#8217;ll list these from what I think is least important to most important.<\/p>\n<h4>#6: Better Script Handling<\/h4>\n<p>Internally, a JSScript represents (more or less) the code of a JS function, including things like the internal bytecode that SpiderMonkey generates for it.\u00a0 The memory used by JSScripts is measured by the \u201cgc-heap\/scripts\u201d and \u201cscript-data\u201d entries in about:memory.<\/p>\n<p>Luke Wagner did some measurements that showed that <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=678037\">most (70\u201380%) JSScripts created in the browser are never run<\/a>.\u00a0 In hindsight, this isn\u2019t so surprising \u2014 many websites load libraries like jQuery but only use a fraction of the functions in those libraries.\u00a0 If SpiderMonkey could be changed to generate bytecode for scripts lazily, it could reduce \u201cscript-data\u201d memory usage by 60\u201370%.\u00a0 This would also allow the <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=718969\">decompiler to be removed<\/a>, which would be great.<\/p>\n<p>Luke also proposed <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=679942\">sharing immutable parts of scripts between web pages<\/a>.\u00a0 This would avoid a lot of duplication in the case where you have many tabs open with pages from a single site.<\/p>\n<p>Both of these changes potentially will make the browser faster as well, because SpiderMonkey will spend less time compiling JavaScript source code to bytecode.<\/p>\n<p>No-one is assigned to work on these bugs.\u00a0 The lazy script creation can be done entirely within the JS engine;\u00a0 the script sharing requires assistance from Necko.\u00a0 Luke is currently busy with some other <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=650353\">righteous refactorings<\/a>, but I&#8217;m quietly hoping once they&#8217;re done he might find time for one or both of these bugs.<\/p>\n<h4>#5: Better Memory Reporting<\/h4>\n<p>Before you can reduce memory consumption you have to measure it.\u00a0 about:memory is the critical tool that has facilitated much of MemShrink&#8217;s work.\u00a0 (For example, we never would have known about <a href=\"https:\/\/developer.mozilla.org\/en\/Zombie_Compartments\">zombie compartments <\/a>without it.)\u00a0 It&#8217;s in pretty good shape now but there are two major improvements that can be made.<\/p>\n<p>First, the &#8220;heap-unclassified&#8221; number (a.k.a &#8220;dark matter&#8221;) is still typically around 20&#8211;25%.\u00a0 My goal is to reduce that to 10%. This won&#8217;t require any great new insights, we already have the <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=676724\">tools<\/a> and <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=563700\">data<\/a> required.\u00a0 Rather, it&#8217;s just a matter of grinding through the list of memory reporters that need to be added and improved.<\/p>\n<p>Second, the resources used by each browser tab are reported in an unwieldy fashion:\u00a0 JS memory on a per-compartment basis;\u00a0 layout memory on a per-docshell basis;\u00a0 DOM memory on a per-window basis.\u00a0 Only a few internal architectural changes stand in the way of uniting these to provide the oft-requested feature of <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=687724\">per-tab memory reporting<\/a>.\u00a0 This will be great for users, because if Firefox is using more memory than they&#8217;d like, it tells them which tabs they should close in order to free up memory.<\/p>\n<p>I am actively working on both these improvements, and I&#8217;m hoping that within a couple of months they&#8217;ll be mostly done.<\/p>\n<h4>#4: Better Memory Consumption Tracking<\/h4>\n<p>One thing we haven&#8217;t done well in MemShrink is to improve the state of tracking Firefox&#8217;s memory consumption.\u00a0 We have plenty of anecdotes but not much hard data about the improvements we&#8217;ve made, and we don&#8217;t have good ways to detect any regressions.\u00a0 A <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=619558\">couple<\/a> of <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=695072\">ideas<\/a> haven&#8217;t gone very far, but some good news is that John Schoenick is making great progress on a proper <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=704646\">areweslimyet.com<\/a> implementation.\u00a0 John has demonstrated preliminary versions of the site at two MemShrink meetings and it&#8217;s looking very promising.\u00a0 It uses the <a href=\"https:\/\/wiki.mozilla.org\/QA\/Mozmill_Test_Automation\/Endurance_Tests\">endurance test framework<\/a> to make the measurements, and opens lots of pages from the Talos tp5 pageset.<\/p>\n<p>We also hope to use telemetry data to analyze how the memory consumption of each released version of Firefox stacks up.\u00a0 That analysis would come with a significant delay &#8212; weeks or months after each release &#8212; but it would be much more comprehensive than any oft-run benchmark, coming from the real-world usage patterns of thousands of users.<\/p>\n<h4>#3: Compacting Generational GC<\/h4>\n<p>If you look in about:memory, JavaScript memory usage usually dominates.\u00a0 In particular, the &#8220;js-gc-heap&#8221; is usually large.\u00a0 There&#8217;s also the &#8220;js-gc-heap-unused-fraction&#8221; number, often 30% or higher, which tells you how much of that space is unused because of fragmentation.\u00a0 That percentage overstates things somewhat, because often a good proportion of that unused space (see &#8220;js-gc-heap-decommitted&#8221;) is decommitted, which means that it&#8217;s costing nothing but address space&#8230; but that is cold comfort if you&#8217;re suffering out-of-memory aborts on Windows due to virtual memory exhaustion.<\/p>\n<p>A compacting garbage collector is one that can move objects around the heap, filling up all those little gaps that constitute fragmentation.\u00a0 The JS team (especially Bill McCloskey and Terrence Cole) is implementing a <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=619558\">compacting generational garbage collector<\/a>, which is a particular kind that tends to have good performance.\u00a0 In particular, many objects die young and generational collectors find these quickly, which means that the heap will grow at a significantly slower rate than it currently does.\u00a0 I could be wrong, but I&#8217;m convinced this will be a big win for both memory consumption and speed.<\/p>\n<h4>#2: Better Foreground Tab Image Handling<\/h4>\n<p>Images are stored in a compressed format (e.g. JPEG, PNG, GIF) on disk.\u00a0 In order to display them, a browser must decompress (a.k.a decode) the compressed form into a raw pixel form that can easily be ten times larger.\u00a0 This decoded form can be discarded and regenerated as necessary, and there are trade-offs to be made &#8212; for example, if you are too aggressive in discarding decoded images, you might have to decode them again, which will take CPU cycles and the user might see flickering if the decoding occurs in the visible part of the page.<\/p>\n<p>However, Firefox goes way too far in the other direction.\u00a0 If you open a page in the foreground tab, every single image in that page will be immediately decoded, and none of the decoded data will be discarded unless you switch away to another tab.\u00a0 For pages that contain many images, this is a recipe for horrific memory consumption, and Firefox does much worse than all the other browsers.\u00a0 So this is a problem that doesn&#8217;t rear its head for all users, but it&#8217;s terrible for those that are affected.<\/p>\n<p>There are three MemShrink:P1 bugs relating to this:\u00a0 one about <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=542158\">not decoding all images immediately<\/a>, one about <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=661304\">discarding non-visible decoded images after some time<\/a>, and one about <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=689623\">some infrastructure work<\/a> that is required for the first two.\u00a0 As far as I know, no progress has been made on these three bugs, and although two of them are assigned they are not being actively worked on.<\/p>\n<p>(See <a href=\"https:\/\/groups.google.com\/forum\/#!topic\/mozilla.dev.platform\/9JZhTxGlG8k\/discussion\">this discussion<\/a> on the dev-platform mailing list for more details about this topic.)<\/p>\n<h4>#1: Better Detection and Notification of Leaky Add-ons<\/h4>\n<p>It&#8217;s been the case for several months that when a user complains about Firefox consuming an excessive amount of memory, it&#8217;s usually because of one or more add-ons, and the &#8220;can you try that again in safe mode?&#8221; \/ &#8220;oh yeah, that fixes it&#8221; dance is getting tiresome.<\/p>\n<p><a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=700547\">Many add-ons leak<\/a>.\u00a0 Even popular, well-written ones:\u00a0 in the past few months leaks have been found in Adblock Plus, Video DownloadHelper, GreaseMonkey and <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=669730\">Firebug<\/a>.\u00a0 That&#8217;s four of the top five add-ons on <a href=\"http:\/\/addons.mozilla.org\/\">AMO<\/a>!\u00a0 We&#8217;re now getting several reports about leaky add-ons a week;\u00a0 in this week&#8217;s MemShrink meeting there were four:\u00a0 <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=719329\">TorButton<\/a>, <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=720591\">NoSquint<\/a>, <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=719782\">Customize Your Web<\/a>, and <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=719601\">1Password<\/a>.\u00a0 I strongly suspect the leaks we know about are just the tip of the iceberg.<\/p>\n<p>Although leaks in add-ons are not Mozilla&#8217;s fault, they are Mozilla&#8217;s problem:\u00a0 Firefox gets blamed for the sins of its add-ons.\u00a0 And it&#8217;s not just memory consumption;\u00a0 the story is the same for performance in general.\u00a0 Here&#8217;s the <a href=\"http:\/\/support.agilebits.com\/discussions\/browser-extensions\/1257-firefox-performance-degrades-with-extension\">quote of the week<\/a>, from a user of 1Password:<\/p>\n<blockquote><p>I only use a handful of extensions and honestly never suspected 1P, however after disabling it I noticed my FireFox performance increased very noticibly. I&#8217;ve been running for 48 hours now without the 1P extension in Firefox and wow what a difference. Browsing is faster, switching is faster, memory usage is way down.<\/p><\/blockquote>\n<p>I&#8217;ve lost count of the number of stories like this that I&#8217;ve heard.\u00a0 How many users have we lost to Chrome because of these issues, I wonder?<\/p>\n<p>(And it&#8217;s not just leaks.\u00a0 See <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=720236\">this analysis<\/a> of 16 add-ons and their effect on memory consumption when Firefox starts.)<\/p>\n<p>One small step towards improving this situation was made this week:\u00a0 Jorge Villalobos and Andrew Williamson added a &#8220;check for memory leaks&#8221; item to the <a href=\"https:\/\/wiki.mozilla.org\/AMO:Editors\/EditorGuide\/AddonReviews\">AMO review checklist<\/a> (under &#8220;Memory leaks from content&#8221;).\u00a0 And Kris Maglione added some support for this checking in his <a href=\"https:\/\/addons.mozilla.org\/addon\/extension-test\/versions\/2.7b1\">Extension Test<\/a> add-on.\u00a0 This means that add-ons with obvious memory leaks (and many of them are obvious if you are actively looking for them) will not be accepted by AMO.<\/p>\n<p>So that will prevents leaks in some new add-ons and new versions of established add-ons.\u00a0 What about existing add-ons?\u00a0 One idea is that AMO could also have <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=695481\">a flag<\/a> that indicates add-ons that have known memory problems (and other performance problems).\u00a0 (This flag wouldn&#8217;t be an automatic thing, it would only be set once a leak has been confirmed, and after giving the author notification and some time to fix the problem.)\u00a0 So that would also improve things a bit.<\/p>\n<p>But lots of add-ons aren&#8217;t hosted on AMO.\u00a0 Another idea is to have a <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=720856\">stronger mechanism<\/a>, one that informs the user if they have any add-ons installed that are known to cause high memory consumption (or other bad performance problems).\u00a0 There is an existing mechanism for blocking add-ons that are known to be malware or exceptionally crashy, so hopefully the warnings could piggy-back on top of that.<\/p>\n<p>Then, we need a better way to detect leaky add-ons.\u00a0 Currently this is entirely done manually &#8212; and a couple of excellent contributors have found leaks on multiple add-ons &#8212; but I&#8217;m hoping that it&#8217;ll be possible to do a much more thorough job by analyzing telemetry data to find out which add-ons are correlated with high memory consumption.\u00a0 That information could be used to trigger manual checking.<\/p>\n<p>Finally, once you know an add-on leaks, it&#8217;s not always easy to work out why.\u00a0 <a href=\"https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=695348\">Tools<\/a> could help a lot here, if they can be made to work well.<\/p>\n<h3>Conclusion<\/h3>\n<p>I listed six big areas for improvement. If we fixed all of these I think we&#8217;d be in a fantastic position.<\/p>\n<p>Three of them (#5 better memory reporting, #4 better memory consumption tracking, #3 compacting generational GC) have people working on them and are in a good state.<\/p>\n<p>Three of them (#6 better script handling, #2 better foreground image tab handling, #1 better detection and notification of leaky add-ons) don&#8217;t have people working on them, as far as I know.\u00a0 If you are willing and have the skills to contribute to any of these areas, please contact me!<\/p>\n<p>And if you think I&#8217;ve overestimated or underestimated the importance of any issue, I&#8217;d love to hear about it.\u00a0 Thanks!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There wasn&#8217;t much MemShrink activity this week in terms of bugs fixed, just bug 718100 and bug 720359.\u00a0 So I&#8217;m going to take the opportunity this week to talk about the bigger picture. Bug Counts As a prelude, here are this week&#8217;s bug counts. P1: 20 (-4\/+0) P2: 131 (-3\/+3) P3: 74 (-2\/+7) Unprioritized: 4 [&hellip;]<\/p>\n","protected":false},"author":139,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4550,4559,119,30,4555,4544,4546],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/posts\/1668"}],"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=1668"}],"version-history":[{"count":0,"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/posts\/1668\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/media?parent=1668"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/categories?post=1668"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mozilla.org\/nnethercote\/wp-json\/wp\/v2\/tags?post=1668"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}