Categories
about:memory add-ons Firefox Garbage Collection Memory consumption MemShrink

MemShrink progress, week 37

It’s been a huge week for MemShrink.

Add-ons

I filed a bug on testing the top 100 add-ons for memory leaks.  The majority of these add-ons are not available on AMO and so are not subject to the leak checking done during AMO reviews.  The instructions and current test results are here.  Randell Jesup helped identify some some add-ons with unclear identities, and Nils Maier and Archaeopteryx have both tested several add-ons.  A month ago I said that add-ons that leak are the #1 problem for MemShrink, and this bug represents a huge step towards reducing that problem.  We’ll need lots of additional help to test this many add-ons, so please feel free to jump in!

As far as I know, comprehensive testing of the most popular add-ons has never been done before.  Although this testing is aimed at finding memory leaks, it’s quite possible it will uncover various other problems with add-ons.  Indeed, it’s clear just from looking at the list that quite a few of the non-AMO add-ons are of dubious merit, and this has stimulated some interesting discussion on dev-platform about third-party add-ons, i.e. those that are installed into Firefox by an external program.

The following add-ons had leaks fixed or mostly fixed by their authors: McAfee Site Advisor, Ghostery, Spool, Screengrab (fix version), Roboform, UF Comment Board ToolsGeenstijl, Long URL Please, HTML Desktop Notifications.

Nils Maier greatly improved the documentation on common causes of memory leaks in add-ons.  This was a MemShrink:P1 bug.  That doesn’t mean the document can’t be improved further, however;  it’s a wiki so please continue to add to it if you can.

Regression testing

John Schoenick’s excellent areweslimyet.com is getting close to being ready for a public unveiling.  The site is currently live but password-protected, simply to prevent large numbers of people accessing it before it’s ready.  (If you want a sneak peek, contact me for the password.)  More importantly, it identified a large regression in memory consumption caused by the landing of the JS engine’s incremental garbage collector on February 19, which Bill McCloskey is investigating.

Tim Taubert improved Firefox’s regression testing to ensure that no new DocShell and DOMWindow leaks are introduced.  This was a MemShrink:P1 bug because these leaks are quite easy to introduce.  Tim wrote some more about this change here.

Cycle collector

Jan Honza Odvarko’s about:ccdump add-on made it onto AMO this week.  Jan has been using this to hunt down some tricky leaks in Firebug.

Marco Bonardo fixed a leak in PlacesUtils.removeLazyBookmarkObserver() that I won’t pretend to understand, but which was a MemShrink:P1.  Marco also fixed a leak that occurred after bookmarking a page, closing the window, and opening a new window.

Olli Pettay fixed an equally impenetrable (to me) leak involving nsFormFillController::mFocusedInput.

Kyle Huey fixed a leak in the About Firefox dialog.

Andrew McCreight added additional information to cycle collector’s error console logging, which helps with identifying and debugging cycle collector problems.

Miscellaneous

Jason Duell fixed an obscure leak involve web sockets.

Bill McCloskey fixed a minor JS engine leak.

I added a new memory reporter called “js/runtime/gc-marker”.  It starts out at 256KB and I saw it reach 2.8MB when running MemBench.  I also converted the existing source image reporters to the new style, which seems to haved fixed some bogus results in about:memory as a side-effect.

Quote of the week

Adam Overa of Tom’s Hardware did another browser Grand Prix.  Devin Coldewey used the results from the Grand Prix to conclude that Firefox and Chrome are both great, and which you prefer basically comes down to a matter of taste.  While that is an interesting conclusion, what caught my eye was this comment, by Balaji Viswanathan:

I guess the title could have been “All browsers suck equally bad now”. Firefox and Chrome have grown to become more resources hogs – closer to IE. These days I shudder to fire up the firefox as the memory leaks are terrible. Two hours of Firefox with a Facebook tab is enough to gobble up 25% of my memory. With Chrome, I would have 20 rendering processes showing up when I would have just 3 tabs open.

In the first 2 years of Chrome I had probably 2 or 3 crashes. These days, it crashes every week or so. I long for the 2006 era Firefox – clean, simple and lean. Its been a long time since I have used IE actively and with Safari lesser said the better. For the developers, we have to deal with the ultra slow update cycles of IE and ultraspeed update cycles of Chrome. In short, we are getting worse and worse in the browser arena. The market is ripe for a breakthrough.

“2006 era Firefox” would have been Firefox 1.5 or Firefox 2.  Balaji may think he’s nostalgic for browsers of that era, but really he’s nostalgic for the web of that era, which was massively simpler than the web of today.  If Balaji tried Firefox 1.5 or Firefox 2 today — with no HTML5 support, no JavaScript JIT and no hardware acceleration — today, I’m sure he’d quickly decide that 2012-era browsers aren’t so bad after all.  I guess the interesting question is this: why do people blame browsers instead of websites for high resource consumption?

Bug counts

This week’s bug counts:

  • P1: 28 (-5/+5)
  • P2: 129 (-12/+7)
  • P3: 83 (-8/+12)
  • Unprioritized: 2 (-2/+2)

That’s a net reduction of one bug.  But more importantly, there is lots of movement, which is great!  It means that problems are being identified and fixed.

(Finally, commenters please note that I’ve turned on the WP-reCAPTCHA plug-in, and this the first post I’ve written since doing so.  In my testing it’s worked fairly well.  Hopefully it won’t cause problems.)

Categories
about:compartments about:memory add-ons compartments Firefox Memory consumption MemShrink

MemShrink progress, week 36

Lots of activity this week.

Leaky add-ons

I created a new devmo wiki page documenting common causes of memory leaks in add-ons.  I based this on a lovely selection of examples provided by Nils Maier.  Unfortunately, I know almost nothing about writing add-ons and so I’m not happy with the current state of the documentation.  I’ve taken it as far as I can, but it very likely has errors, leaves out important cases, conflates distinct concepts, and generally is not as good as it should be.  This documentation is really important — we have good tools for identifying when add-on leaks occur but we don’t yet have good tools for identifying their causes.  Until we have those tools, documentation is the only way we can help add-on authors fix leaks.  If someone who knows more about add-ons is willing to help please contact me!

Alexandre Poirot fixed a leak in the Add-on SDK that was causing zombie compartments when certain add-ons were disabled.  This also fixed bug 725603 and probably fixes some zombie compartments reported in some other add-ons (e.g. MemChaser).

Jan fixed several leaks in the Galaxytoolbar add-on.  The new version is 2.6.12.

A small number of add-ons have been found that disable Firefox’s XUL cache.  This is a recipe for disastrous performance, and so Matt Basta updated the AMO add-on validator to detect this.

Tools

I landed support for a new page called about:compartments. The exposure of zombie compartments in about:memory has become an extremely powerful leak detection tool.  But using about:memory to find zombies is non-trivial — there are multiple steps and ways to get it wrong.  The motivation for about:compartments is to make the detection of zombie compartments as simple as possible.  Here’s a screenshot:

about:compartments screenshot

Some things to note:

  • It only shows compartments, and all of them.
  • User compartments from web content (usually the interesting ones) are listed separately from system compartments.
  • The garbage and cycle collectors are automatically run when the page is loaded, ensuring that dead compartments aren’t listed.
  • The “More verbose” link at the bottom just causes the truncated URLs to be shown in full.
  • about:compartments shares a lot of code with about:memory.
  • I updated the documentation on zombie compartments accordingly.

Olli Pettay created about:cc, an add-on that can detect various kinds of document leaks relating to cycle collection.  Olli has already found several leaks with this tool.  Jan Honza Odvarko has written about:ccdump, a similar but prettier add-on.  I’m not certain but I think Olli and Jan are now co-ordinating their efforts.

I mentioned Mozilla QA’s MemChaser add-on a few weeks ago.  It lets you track memory usage and GC/CC activity easily via the add-on bar, and also allows logging of memory-related activities.  It’s now available on AMO, which guarantees you’ll receive updates as they’re released.

Jesse Ruderman tweaked his DOM fuzzer and found several new small leaks relating to nsITimers.  Jesse also modified about:memory so that it produces assertions that his fuzzer will catch.  This means that his fuzzer will detect if any memory reporters produce bogus values.

Miscellaneous

Kyle Huey fixed a zombie compartment that occurred when searching within pages with onclick handlers, which is a pretty common operation.

Jeff Muizelaar fixed a huge Mac-only leak relating to text rendering.  This was a recent regression that isn’t present in any released version of Firefox.

Josh Aas fixed a bug in cookie clearing — prior to Josh’s fix, if you cleared all cookies, Firefox would launch an instance of the plugin-container process for every plug-in installed, which could cause freezes and memory spikes.

Andrew Quartey updated the WebGL memory reporters to the new style.

Bug counts

This week’s bug counts:

  • P1: 28 (-1/+3)
  • P2: 134 (-6/+9)
  • P3: 79 (-8/+11)
  • Unprioritized: 2 (-1/+2)

Lots of movement there:  plenty of bugs fixed, but even more new ones.  Roughly 20 of the new ones fell into the following three categories.

  • Zombie compartments found in AMO add-ons by Kris Maglione and Andreas Wagner.
  • Leaks found by Olli Pettay’s new about:cc tool, mentioned above.
  • Leaks found by Jesse Ruderman’s tweaked DOM fuzzer, mentioned above.

This is a good thing!  It shows that new policies and tools are exposing existing problems.  I expect this higher level of new bug filing will continue for a couple of weeks.

Categories
add-ons Firefox Memory consumption

The McAfee Site Advisor add-on has an appalling memory leak

TL;DR: If you have the McAfee Site Advisor add-on installed in your Firefox, I recommend you disable it immediately because it has an appalling memory leak.

I wrote yesterday about a reader’s results with the McAfee Site Advisor 3.4.1 and McAfee ScriptScan 14.4.1 add-ons for Firefox — he was finding that they greatly increased Firefox’s memory consumption.

This morning I tested Site Advisor 3.4.1 myself, and found that, when enabled, it leaks every single content compartment that is createdIn other words, most of the JavaScript memory used for any page opened with Firefox is never reclaimed.  In terms of memory consumption, this is pretty much the worst possible behaviour for an add-on.  This excessive memory consumption is likely to cause Firefox to run much more slowly and crash much more often.

In the bug report I recommended that we block-list it immediately and contact McAfee, but Jorge Villalobos told me that block-listing is considered an option of last resort.  Three McAfee people have been CC’d on the bug and I’ve been told that some other Mozilla people are contacting McAfee via other channels. Hopefully we’ll see concrete action soon.

If anyone else can replicate my results, particularly for older versions of Site Advisor, that would be useful to know.  Steps to reproduce are in the bug report.

As for ScriptScan 14.4.1, I haven’t tried it myself because I haven’t been able to find where to download it from.  My searching just turned up lots of references, such as this one, to when Mozilla block-listed version 14.4.0 because it was crashing so frequently.  (Site Advisor 3.4.0 was block-listed at the same time.  And SiteAdvisor 3.3.1 was also block-listed due to crashes!)  If anyone can tell me where to get ScriptScan from that would be very helpful.

If you have any McAfee add-ons installed in your Firefox, I strongly recommending disabling them immediately.  McAfee clearly has a poor record when it comes to the quality of their Firefox add-ons.  I also personally found Site Advisor to be an extremely annoying and unhelpful add-on.  I’m no expert on Windows security but if you are looking for alternatives I have heard numerous people say that Microsoft Security Essentials is the best anti-virus/security system for Windows — it’s reputedly very effective, and is free of charge and non-intrusive.  It also doesn’t install any add-ons into Firefox.

Categories
add-ons Firefox Memory consumption MemShrink

McAfee is killing us

A reader named AC commented on last week’s MemShrink report that Firefox was consuming lots of memory on his girlfriend’s computer (emphasis added by me):

I am currently on my girlfriends laptop round at her house and I am surfing the net using Firefox 10.0.1. The memory usage is terrible. It may be because of the two McAfee add-ons that she has, I don’t know, but I can see now first hand how some Firefox users are having an amazing experience and others are still lagging behind. The memory usage as opposed to being 200,000-230,000kb as it would be on my laptop with 11 beta 2 is about 350,000kb or more. That said, there is no loss of performance and that is what matters most. I am not looking for answers or solutions, merely saying that the same or very similar software used on one computer can perform completely differently on another and now I appreciate that even more having witnessed it for myself.

I asked him to try turning off the McAfee add-ons, which he kindly did.  The result (emphasis again added by me):

I did some very very rudimentary tests earlier at my girlfriends house on her laptop and here is what I found.

With the two McAfee add-ons running everything was fine until I got to about 8 tabs and then the memory began to increase. Then it just climbed up to about 450,000 kb. If I was running the same tab load on my latop, I would expect just over half that amount of memory to be reported in task manager.

I have to say that there was no loss of performance, but the amount of memory being used was very high for the tab load.

The first tab that I had open was google.co.uk. I right clicked on that tab and hit “Close Other Tabs”. The memory stayed at 418,000 kb and that was it. It stayed at that level for about 10 minutes whilst I went and did other stuff. It wasn’t going up or down. 400MB with just Google UK open and nothing else. It’s diabolical.

So I then disabled the 2 McAfee add-ons and every went back to normal. I used a heavy tab load than before. I opened more tabs with more complex content. I must have had about 15 tabs open and the memory use peaked at 386,000 kb.

Then I logged out of Facebook and Hotmail, without closing any tabs, and within 10 seconds the memory had dropped to 330,000 kb.

Then I closed all but 3 tabs and within 30 seconds the memory was about 180,000.

Then I closed all but one tab and the memory settled at just under 100,000 kb. Back to normal. Exactly how I would expect Firefox 10.0.1 to perform.

The extensions in question were McAfee ScriptScan for Firefox 14.4.1 and McAfee Site Advisor 3.4.1

I didn’t have time to test them individually as things got hectic after that, but as you say Nicholas, the seemingly innocent extensions were ruining the memory performance of a perfectly good browser.

I could still load pages etc and navigate around as fast, but the numbers on task manager were sky high.

Firefox has a reputation in particular for not releasing memory when tabs are closed.  75% of installed add-ons are not hosted on AMO, and thus are out of Mozilla’s control.  This is killing us.  Bug 720856 is my best suggestion for dealing with badly written add-ons such as these ones, but even it feels like weak tea when the problem is so large.

Categories
Meta

Blog hassles

The Mozilla WordPress installation was upgraded a couple of days ago.  I had a simple captcha plug-in enabled before this (I don’t remember it’s name).  It asked you to solve a very simple arithmetic problem (e.g. “what is 1+1”) before your comment would appear.  It was very effective at stopping spam comments.  Prior to me enabling it I would get  numerous spam comments per post which I had to manually delete.

After the upgrade, this plug-in doesn’t seem to be available any more.  There’s a plug-in called “simple CAPTCHA” which is a picture-based one.  I turned it on but some people reported problems, there were some double-posts, and when I tested it the captcha image didn’t load properly.  Furthermore, spam comments still seemed to be getting through.

Any suggestions?  None of the other spam-fighting plug-ins seem appropriate.  Really, I just want my simple arithmetic problem captcha back.  If I can’t get something working I might have to require people login before commenting.  But I’d rather not do that, as it will deter some commenters.

Categories
about:memory add-ons Firefox Memory consumption MemShrink

MemShrink progress, week 35

Add-ons

Zombie compartments were fixed in the following add-ons:  Customize Your Web (fixed by Rudolf Noe), GridTube (fixed by Costas B.), Do Not Track Plus (fixed by kiran).

Marco Bonardo changed the Places JS services in a way that prevents certain kinds of SQLite connection leaks.  As far as I can tell, this fixes leaks in the Delicious Bookmarks and CyberSearch add-ons.

Finally, Alexandre Poirot fixed a bug in the Add-on SDK that was causing zombie jetpack compartments in some cases when add-ons were disabled.

Memory Reporting

Hugh Nougher added a memory reporter for GPU memory on Windows 7 and Vista.  See the “gpu-committed”, “gpu-dedicated” and “gpu-shared” entries in about:memory’s “Other Measurements” list.

I reduced the amount of memory allocated when generating about:memory by about 35%.

Miscellaneous

Josh Aas implemented unloading for out-of-process plug-ins.  If one is unused for 3 minutes it will be unloaded.

Andrew McCreight improved cycle collector dumping, which is useful in certain debugging cases.

Quote of the week

LifeHacker did some browser performance tests.  Firefox 10 handily won the memory usage test, which involved loading sites in 9 tabs and then measuring.  I personally think this is a pretty meaningless test, but I won’t complain about the good press.

As usual, the comments on the article featured a lot of debate about  whether Firefox is a memory hog or not.  One comment particular caught my attention:

They hardly used to be myths. I saw several times when old FF2x would be taking up over 1.4GB of RAM with just half a dozen tabs open.

Firefox 2 was released in October 2006, and superseded by Firefox 3 in June 2008.  Bad reputations are really difficult to shake.

Bug counts

This week’s bug counts:

  • P1: 26 (-0/+4)
  • P2: 131 (-6/+3)
  • P3: 76 (-2/+3)
  • Unprioritized: 1 (-2/+1)
Categories
about:memory add-ons Firefox Memory consumption MemShrink

MemShrink progress, week 34

Add-ons

The AMO add-on review checklist was amended a couple of weeks ago to include checks for zombie compartments.  This change is bearing fruit:  Andreas Wagner and Kris Maglione have found more than 10 submitted add-ons that have leaks.  See here, here, here, here, here.  With the experience they are gaining, we should be able to greatly improve the documentation on common causes of leaks.

In less positive news, two leaks were found in the add-on SDK.  Fortunately the SDK team has proven to be effective at fixing identified leaks quickly in the past, hopefully they’ll do so again!

Finally, Jason Tackaberry fixed a zombie compartment in NoSquint 2.1.2.  The fix is in the latest version (2.1.5).

about:nosy

Andrew Sutherland wrote a extension called about:nosy which is like about:memory on steroids.  It’s oriented around hiding many of the details and instead assigning blame for memory allocations to particular tabs (and similar things).  It also features graphs showing how the memory consumption of each tracked entity changes over time;  this latter feature is quite memory and CPU-intensive, however.  If you are running a recent Nightly build of Firefox, download about:nosy here and you won’t even have to restart Firefox to see it, just type “about:nosy” into the address bar.

Forthcoming changes will make about:memory more like about:nosy, by measuring more things on a per-tab basis.  And for a long time I have had a vague plan that one day someone who knows about UX will write a user-friendly alternative to about:memory that focuses just on per-tab memory consumption, and about:nosy is a good indicator of what that might look like.

Miscellaneous

Saptarshi Guha from the metrics team did an analysis of the physical memory consumption of Firefox 10, 11 and 12, based on telemetry data.  The post is heavy going for those who aren’t experts at statistics and R, but the two main conclusions of interest are (a) that add-ons significantly increase resident memory consumption, and (b) Firefox 12 is consuming more resident memory than Firefox 11.  This latter fact matches something we’d seen in today’s MemShrink meeting when looking at data from John Schoenick’s in-development version of areweslimyet.com — something in early January caused a significant memory consumption regression.  John is working on narrowing down which change caused this.

Gian-Carlo Pascutto overhauled the safe browsing implementation.  I don’t claim to understand this change at all, but I think it reduces memory consumption when the database is updated.  Better explanations from those who understand this change are welcome!

I reduced the amount of memory allocated when generating about:memory by roughly 30%.

I wrote a detailed discussion of the benefits of reducing memory consumption.

Bug Counts

Here are this week’s bug counts.

  • P1: 22 (-0/+0)
  • P2: 134 (-4/+8)
  • P3: 75 (-3/+4)
  • Unprioritized: 2 (-2/+1)
Categories
Firefox Memory consumption MemShrink

The benefits of reducing memory consumption

TL;DR: Any single change that reduces Firefox’s memory consumption can affect Firefox’s speed, stability and reputation in a variety of ways, some of which are non-obvious.  Some examples illustrate this.

The MemShrink wiki page starts with the following text.

MemShrink is a project that aims to reduce Firefox’s memory consumption. There are three potential benefits.  Speed. […] Stability. […] Reputation.”

I want to dig more deeply into these benefits and the question of what it means to “reduce Firefox’s memory consumption”, because there are some subtleties involved.  In what follows I will use the term “MemShrink optimization” to refer to any change that reduces Firefox’s memory consumption.

Speed

People tend to associate low memory consumption with speed.  However, time/space trade-offs abound in programming, and an explicit goal of MemShrink is to not slow Firefox down — the wiki page says:

Changes that reduce memory consumption but make Firefox slower are not desirable.

There are several ways that MemShrink optimizations can improve performance.

Paging

The case that people probably think of first is paging.  If physical memory fills up and the machine needs to start paging, i.e. evicting virtual memory pages to disk space, it can be catastrophic for performance.  This is because disk accesses are many thousands of times slower than RAM accesses.

However, some MemShrink optimizations are far more likely to affect paging than others.  The key idea here is that of the working set size — what’s important is not the total amount of physical or virtual memory being used, but the fraction of that memory that is touched frequently.  For example, consider two programs that allocate and use a 1GB array.  The first one touches pages within the array at random.  The second one touches every page once and then touches the first page many times.  The second program will obviously page much less than the first if the system’s physical memory fills up.

The consequence of this is that a change that reduces the size of data structures that are accessed frequently is much more likely to reduce paging than a change that reduces the size of data structures that are accessed rarely.  Note that this is counter-intuitive!  It’s natural to want to optimize data structures that are wasteful of space, but “wasteful of space” often means “hardly touched” and so such optimizations don’t have much effect on paging.

Measuring the working set size of a complex program like a web browser is actually rather difficult, which means that gauging the impact of a change on paging is also difficult.  Julian Seward’s virtual memory profiler offers one possible way.  Another complication is that results vary greatly between machines.  If you are running Firefox on a machine with 16GB of RAM, it’s likely that no change will affect paging, because Firefox is probably never paging in the first place.  If you are on a netbook with 1GB of RAM, the story is obviously different.  Also, the effects can vary between different operating systems.

Cache pressure

Some MemShrink optimizations can also reduce cache pressure.  For example, a change that makes a struct smaller would allow more of them to fit into a cache line.  Like paging, these effects are very difficult to quantify, and changes that affect hot structures are more likely to reduce cache pressure significantly and improve performance.

Structure traversals

Sometimes large data structures must be traversed, and reducing the number of elements in the data structure can reduce that traversal time.  The obvious case for Firefox is the JavaScript heap — the garbage collector and cycle collector frequently traverse it, and so any change that causes dead objects to accumulate more slowly will reduce their traversal times.

Only a small fraction of MemShrink optimizations will speed up structure traversals.

Stability

If Firefox (or any program) uses too much memory, it can lead to aborts and crashes.  These are sometimes called “OOMs” (out of memory). There are two main kinds of OOM:  those involving virtual memory, and those involving physical memory.

Virtual OOMs

A “virtual OOM” occurs when the virtual address space fills up and Firefox simply cannot refer to any more memory.  This is mostly a problem on Windows, where Firefox is distributed as a 32-bit application, and so it can only address 2GB or 4GB of memory (the addressable amount depends on the OS configuration).  This is true even if you have more than 4GB of RAM.  In contrast, Mac OS X and Linux builds of Firefox are 64-bit and so virtual memory exhaustion is essentially impossible because the address space is massively larger.

(I don’t want to get distracted by the question of why Firefox is a 32-bit application on Windows.  I’ll just mention that (a) many Windows users are still running 32-bit versions of Windows that cannot run 64-bit applications, and (b) Mozilla does 64-bit Windows builds for testing purposes.  Detailed discussions of the pros and cons of 64-bit builds can be read here and here.)

The vast majority of MemShrink optimizations will reduce the amount of virtual memory consumed.  (The only counter-examples I can think of involve deliberately evicting pages from physical memory.  E.g. see the example of the GC decommitting change discussed below.)  And any such change will obviously reduce the number of virtual OOMs.  Furthermore, the effect of any reduction is obvious and straightforward — a change that reduces the virtual memory consumption by 100MB on a particular machine and workload is twice as good as one that reduces it by 50MB.  Of course, any improvement will only be noticed by those who experience virtual OOMs, which typically is people who have 100s of tabs open at once.  (It may come as a surprise, but some people have that many tabs open regularly.)

Physical OOMs

A “physical OOM” occurs when physical memory (and any additional backing storage such as swap space on disk) fills up.  This is mostly a problem on low-end devices such as smartphones and netbooks, which typically have small amounts of RAM and may not have any swap space.

The situation for physical memory is similar to that for virtual memory:  almost any MemShrink optimization will reduce Firefox’s physical memory consumption.  (One exception is that it’s possible for a memory allocation to consume virtual memory but not physical memory if it’s never accessed;  more about this in the examples section below.)  And any reduction in physical memory consumption will in turn reduce the number of physical OOMs.  Finally, the effects are again obvious and straightforward — a 100MB reduction is twice as good as a 50MB reduction.

Reputation

Finally, we have reputation.  The obvious effect here is that if MemShrink optimizations cause Firefox to become faster and more stable over time, people’s opinion of Firefox will rise, either because their own experience improves, or they hear that other people’s experience improves.

But I want to highlight a less obvious aspect of reputation.  People often gauge Firefox’s memory consumption by looking at a utility such as the Task Manager (on Windows) or ‘top’ (on Mac/Linux).  Interpreting the numbers from these utilities is rather difficult — there are multiple metrics and all sorts of subtleties involved.  (See this Stack Overflow post for evidence of the complexities and how easy it is to get things wrong.)  In fact, in my opinion, the subtleties are so great that people should almost never look at these numbers and instead focus on metrics that are influenced by memory consumption but which they can observe directly as users, i.e. speed and crash rate… but that’s a discussion for another time.

Nonetheless, a non-trivial number of people judge Firefox on this metric.  Imagine a change that caused Firefox’s numbers in these utilities to drop but had no other observable effect.  (Such a change may be impossible in practice, but that doesn’t matter in this thought experiment.)  One thing that has consistently surprised me is that some people view memory consumption as something approaching a moral issue:  low memory consumption is virtuous and high memory consumption is sinful.  As a result, this hypothetical change would improve Firefox’s reputation, rightly or wrongly, for the better.

Let’s call this aspect of Firefox’s reputation the “reputation-by-measurement”.  I suspect the most important metric for reputation-by-measurement is the “private bytes” reported by the Windows Task Manager, because that’s what people seem to most often look at.  Private bytes measures the virtual memory of a process that is not shared with any other process.  It’s my educated guess that in Firefox’s case that the amount of shared memory isn’t that high, and so the situation is similar to virtual OOMs above — just about any change that reduces the amount of virtual memory will reduce the private bytes by the same amount, and in terms of reputation-by-measurement, a 100MB reduction is twice as good as a 50MB reduction.

Examples

Some examples help bring this discussion together.  Consider bug 609905, which removed a 512KB block of memory that was found to be allocated but never accessed.  (This occurred because some code that used that block was removed but the allocation wasn’t removed at the same time.)  What were the benefits of this change?

  • The 512KB never would have been in the working set, so performance would not have been affected.
  • Virtual memory consumption would have dropped by 512KB, slightly reducing the likelihood of virtual OOMs.
  • Physical memory consumption probably didn’t change — because the block was never accessed, it probably never made it into physical memory.
  • Private bytes would have dropped by 512KB, slightly improving reputation-by-measurement.

Now consider bug 670596, which made the JavaScript garbage collector decommit (i.e. remove from physical memory and backing storage) 1MB heap chunks that are unused.  What were the benefits of this change?

  • Performance may have improved slightly due to reduced paging, on machines where paging happens.  Those chunks are clearly not in the working set when they are decommitted, but if paging occurs, the pre-emptive removal of some pages from physical memory may prevent the OS from having to evict some other pages, some of which might have been in the working set.
  • Virtual memory consumption would not have changed at all, because decommitted memory still takes up address space.
  • Physical memory consumption would have dropped by the full decommit amount — 10s or even 100s of MBs in many cases when decommitting is triggered — significantly reducing the likelihood of physical OOMs.
  • Private bytes would not have changed, leaving reputation-by-measurement unaffected. [Update: Justin Lebar queried this. This page indicates that decommitting memory does reduce private bytes, which means that this change would have improved reputation-by-measurement.]

Another interesting one is bug 676457.  It fixed a problem where PLArenaPool was requesting lots of allocations of ~4,128 bytes.  jemalloc rounded these requests up to 8,192 bytes, so almost 50% of each 8,192 byte block was wasted, and there could be many of these blocks.  The patch fixed this by reducing the requests to 4,096 bytes which is a power-of-two and not rounded up (and also usually the size of an OS virtual memory page).  What were the benefits of this change?

  • Performance may have improved due to less paging, because the working set size may have dropped.  The size of the effect depends how often the final 32 used bytes of each chunk — those that spilled onto a second page — are accessed.  For at least some of the blocks those 32 bytes would never be touched.
  • Virtual memory consumption dropped significantly, reducing the likelihood of virtual OOMs.
  • Physical memory consumption may have dropped, but it’s not clear by how much.  In cases where the extra 32 bytes are never accessed, the second page might not have ever taken up physical memory.
  • Private bytes would have dropped by the same amount as virtual memory, improving reputation-by-measurement.

Finally, let’s think about a compacting, generational garbage collector, something that is being worked on by the JS team at the moment.

  • Performance improves for three reasons.  First, paging is reduced because of the generational behaviour:  much of the JS engine activity occurs in the nursery, which is small;  in other words, the memory activity is concentrated within a smaller part of the working set.  Second, paging is further reduced because of the compaction: this reduces fragmentation within pages in the tenured heap, reducing the total working set size.  Third, the tenured heap grows more slowly because of the generational behaviour: many objects are collected earlier (in the nursery) than they would be with a non-generational collector, which means that structure traversals done by the garbage collector (during full-heap collections) and cycle collector are faster.
  • Virtual memory consumption drops in two ways.  First, the compaction minimizes waste due to fragmentation.  Second, the heap grows more slowly.
  • Physical memory consumption drops for the same two reasons.
  • Private bytes also drops for the same two reasons.

A virtuous change indeed.

Conclusion

Reducing Firefox’s memory consumption is a good thing, and it has the following benefits.

  • It can improve speed, due to less paging, fewer cache misses, and faster structure traversals.  These changes are likely to be noticed more by users on lower-end machines.
  • It improves stability by reducing virtual OOM aborts, which mostly helps heavy tab users on Windows.  It also improves stability by reducing physical OOM aborts, which mostly affects heavy-ish tab users on small devices like smartphones and netbooks.
  • It improves reputation among those whose browsing experience is improved by the above changes, and also among users who make judgments according to memory measurements with utilities like the Windows Task Manager.

Furthermore, when discussing MemShrink optimizations, it’s a good idea to describe improvements in these terms.  For example, instead of saying “this change reduces memory consumption”, one could say “this change reduces physical and virtual memory consumption and may reduce paging”.  I will endeavour to do this myself from now on.

Categories
about:memory add-ons Firefox Memory consumption MemShrink

MemShrink progress, week 33

about:memory

Up until this week, about:memory was a static pages;  once generated, it couldn’t change.  This week, I landed a patch that makes every sub-tree expandable and collapsible.    This can be quite useful, because it gives you fine control over what details to ignore.  The following screenshot shows an example where all the level 1 sub-trees in the “explicit” tree are collapsed except for “startup-cache”.  (++ indicates sub-trees that can be expanded, -- indicates sub-trees that can be collapsed, and the remaining nodes (such as “heap-unclassified”) are leaf nodes).

a mostly-collapsed "explicit" tree in about:memory

I also changed about:memory so that obviously bogus values (e.g. negative values, percentages greater than 100%) are highlighted.  These indicate bugs in memory reporters, and so we want to know about them.

Memory Reporters

I added new memory reporters for style sheets.  This was the single biggest remaining chunk of dark matter.  On a 64-bit Linux build, this reduces the “heap-unclassified” count when I have Gmail and TechCrunch open from ~23% to ~15%.  The counts mostly show up under the “explicit/dom+style” sub-tree, in “style-sheets” leaf nodes.

I also simplified the writing of memory reporters by removing the need for the computedSize argument when measuring the size of a heap block.

Finally, if you create a sandbox with Components.utils.Sandbox, you can specify a name and about:memory will use that name to identify the sandbox’s compartment.  Sander van Veen made it so that sandboxes that aren’t given a name will use the  their callers’ filename as a name.  In other words, all sandboxes should now be identifiable in about:memory.

leaks

Brian Hackett fixed a leak in JaegerMonkey.

Andrew McCreight fixed a leak caused by watchpoints, which are used when debugging JavaScript code.

A leak related to JavaScript sharps (a non-standard, SpiderMonkey-only feature) was fixed by Jeff Walden when he removed support for sharps 🙂

Add-ons

I mentioned last week that I think leaky add-ons are the #1 problem for Firefox’s memory consumption, and mentioned the idea of telling users when they have an add-on installed that is known to have performance problems.  Bug 720856 is open for this.  Asa Dotzler, Firefox Product Manager, said:

I will secure Firefox client developer resources for this feature where I have some input into resourcing. If this plan is deemed appropriate, I will work with Justin to secure AMO side resources as well and we can nail this problem.

We can’t keep going back and forth on this while our users suffer. We must act now. I understand that defining “bad add-ons” will be contentious but so long as the technical approach is righteous we can sort out how heavy handed we want to be on policy at a later time and move forward implementing this today.

There was already a feature page covering this basic idea, and Asa updated it. This feature would be a huge help to users.  Fingers crossed we’ll see some progress soon!

Henrik Skupin has started working on an add-on called MemChaser (download it here) which is aimed at helping detect problems relating to memory consumption.  Currently it just shows some stats in the add-on bar — resident memory consumption (updated every two seconds), how long the last garbage collection took, and how long the last cycle collection took — but Henrik has many ideas for the future.  Worth watching!

Bug Counts

Here are this week’s bug counts.

  • P1: 22 (-0/+2)
  • P2: 130 (-3/+2)
  • P3: 74 (-2/+2)
  • Unprioritized: 3 (-4/+3)