Category Archives: Google Chrome

How to Compare the Memory Efficiency of Web Browsers

TL;DR: Cross-browser comparisons of memory consumption should be avoided.  If you want to evaluate how efficiently browsers use memory, you should do cross-browser comparisons of performance across several machines featuring a range of memory configurations.

Cross-browser Memory Comparisons are Bad

Various tech sites periodically compare the performance of browsers.  These often involve some cross-browser comparisons of memory efficiency.  A typical one would be this:  open a bunch of pages in tabs, measure memory consumption, then close all of them except one and wait two minutes, and then measure memory consumption again.  Users sometimes do similar testing.

I think comparisons of memory consumption like these are (a) very difficult to make correctly, and (b) very difficult to interpret meaningfully.  I have suggestions below for alternative ways to measure memory efficiency of browsers, but first I’ll explain why I think these comparisons are a bad idea.

Cross-browser Memory Comparisons are Difficult to Make

Getting apples-to-apples comparisons are really difficult.

  1. Browser memory measurements aren’t easy.  In particular, all browsers use multiple processes, and accounting for shared memory is difficult.
  2. Browsers are non-deterministic programs, and this can cause wide variation in memory consumption results.  In particular, whether or not the JavaScript garbage collector runs can greatly reduce memory consumption.  If you get unlucky and the garbage collector runs just after you measure, you’ll get an unfairly high number.
  3. Browsers can exhibit adaptive memory behaviour.  If running on a machine with lots of free RAM, a browser may choose to take advantage of it;  if running on a machine with little free RAM, a browser may choose to discard regenerable data more aggressively.

If you are comparing two versions of the same browser, problems (1) and (3) are avoided, and so if you are careful with problem (2) you can get reasonable results.  But comparing different browsers hits all three problems.

Indeed, Tom’s Hardware de-emphasized memory consumption measurements in their latest Web Browser Grand Prix due to problem (3).  Kudos to them!

Cross-browser Memory Comparisons are Difficult to Interpret

Even if you could get the measurements right, memory consumption is still not a good thing to compare.  Before I can explain why, I’ll introduce a couple of terms.

  • A primary metric is one a user can directly perceive.  Metrics that measure performance and crash rate are good examples.
  • A secondary metric is one that a user can only indirectly perceive via some kind of tool.  Memory consumption is one example.  The L2 cache miss rate is another example.

(I made up these terms, I don’t know if there are existing terms for these concepts.)

Primary metrics are obviously important, precisely because user can detect them.  They measure things that users notice:  “this browser is fast/slow”, “this browser crashes all the time”, etc.

Secondary metrics are important because they can affect primary metrics:  memory consumption can affect performance and crash rate;  the L2 cache miss rate can affect performance.

Secondary metrics are also difficult to interpret.  They can certainly be suggestive, but there are lots of secondary metrics that affect each primary metric of interest, so focusing too strongly on any single secondary metric is not a good idea.  For example, if browser A has a higher L2 cache miss rate than browser B, that’s suggestive, but you’d be unwise to draw any strong conclusions from it.

Furthermore, memory consumption is harder to interpret than many other secondary metrics.  If all else is equal, a higher L2 cache miss rate is worse than a lower one.  But that’s not true for memory consumption.  There are all sorts of time/space trade-offs that can be made, and there are many cases where using more memory can make browsers faster;  JavaScript JITs are a great example.

And I haven’t even discussed which memory consumption metric you should use.  Physical memory consumption is an obvious choice, but I’ll discuss this more below.

A Better Methodology

So, I’ve explained why I think you shouldn’t do cross-browser memory comparisons.  That doesn’t mean that efficient usage of memory isn’t important! However, instead of directly measuring memory consumption — a secondary metric — it’s far better to measure the effect of memory consumption on primary metrics such as performance.

In particular, I think people often use memory consumption measurements as a proxy for performance on machines that don’t have much RAM.  If you care about performance on machines that don’t have much RAM, you should measure performance on a machine that doesn’t have much RAM instead of trying to infer it from another measurement.

Experimental Setup

I did exactly this by doing something I call memory sensitivity testing, which involves measuring browser performance across a range of memory configurations.  My test machine had the following characteristics.

  • CPU: Intel i7-2600 3.4GHz (quad core with hyperthreading)
  • RAM: 16GB DDR3
  • OS: Ubuntu 11.10, Linux kernel version 3.0.0.

I used a Linux machine because Linux has a feature called cgroups that allows you to restrict the machine resources available to one or more processes.  I followed Justin Lebar’s instructions to create the following configurations that limited the amount of physical memory available: 1024MiB, 768MiB, 512MiB, 448MiB, 384MiB, 320MiB, 256MiB, 192MiB, 160MiB, 128MiB, 96MiB, 64MiB, 48MiB, 32MiB.

(The more obvious way to do this is to use ulimit, but as far as I can tell it doesn’t work on recent versions of Linux or on Mac.  And I don’t know of any way to do this on Windows.  So my experiments had to be on Linux.)

I used the following browsers.

  • Firefox 12 Nightly, from 2012-01-10 (64-bit)
  • Firefox 9.0.1 (64-bit)
  • Chrome 16.0.912.75 (64-bit)
  • Opera 11.60 (64-bit)

IE and Safari aren’t represented because they don’t run on Linux.  Firefox is over-represented because that’s the browser I work on and care about the most :)   The versions are a bit old because I did this testing about six months ago.

I used the following benchmark suites:  Sunspider v0.9.1, V8 v6, Kraken v1.1.  These are all JavaScript benchmarks and are all awful for gauging a browser’s memory efficiency;  but they have the key advantage that they run quite quickly.  I thought about using Dromaeo and Peacekeeper to benchmark other aspects of browser performance, but they take several minutes each to run and I didn’t have the patience to run them a large number of times.  This isn’t ideal, but I did this exercise to test-drive a benchmarking methodology, not make a definitive statement about each browser’s memory efficiency, so please forgive me.

Experimental Results

The following graph shows the Sunspider results.  (Click on it to get a larger version.)

sunspider results graph

As the lines move from right to left, the amount of physical memory available drops.  Firefox was clearly the fastest in most configurations, with only minor differences between Firefox 9 and Firefox 12pre, but it slowed down drastically below 160MiB;  this is exactly the kind of curve I was expecting.  Opera was next fastest in most configurations, and then Chrome, and both of them didn’t show any noticeable degradation at any memory size, which was surprising and impressive.

All the browsers crashed/aborted if memory was reduced enough.  The point at which the graphs stop on the left-hand side indicate the lowest size that each browser successfully handled.  None of the browsers ran Sunspider with 48MiB available, and FF12pre failed to run it with 64MiB available.

The next graph shows the V8 results.

v8 results graph

The curves go the opposite way because V8 produces a score rather than a time, and bigger is better.  Chrome easily got the best scores.  Both Firefox versions degraded significantly.  Chrome and Opera degraded somewhat, and only at lower sizes.  Oddly enough, FF9 was the only browser that managed to run V8 with 128MiB available;  the other three only ran it with 160MiB or more available.

I don’t particularly like V8 as a benchmark.  I’ve always found that it doesn’t give consistent results if you run it multiple times, and these results concur with that observation.  Furthermore, I don’t like that it gives a score rather than a time or inverse-time (such as runs per second), because it’s unclear how different scores relate.

The final graph shows the Kraken results.

kraken results graph

As with Sunspider, Chrome barely degraded and both Firefoxes degraded significantly.  Opera was easily the slowest to begin with and degraded massively;  nonetheless, it managed to run with 128MiB available (as did Chrome), which neither Firefox managed.

Experimental Conclusions

Overall, Chrome did well, and Opera and the two Firefoxes had mixed results. But I did this experiment to test a methodology, not to crown a winner.  (And don’t forget that these experiments were done with browser versions that are now over six months old.)  My main conclusion is that Sunspider, V8 and Kraken are not good benchmarks when it comes to gauging how efficiently browsers use memory.  For example, none of the browsers slowed down on Sunspider until memory was restricted to 128MiB, which is a ridiculously small amount of memory for a desktop or laptop machine;  it’s small even for a smartphone.  V8 is clearly stresses memory consumption more, but it’s still not great.

What would a better benchmark look like?  I’m not completely sure, but it would certainly involve opening multiple tabs and simulate real-world browsing. Something like Membench (see here and here) might be a reasonable starting point.  To test the impact of memory consumption on performance, a clear performance measure would be required, because Membench lacks one currently.  To test the impact of memory consumption on crash rate, Membench could be modified to just keep opening pages until the browser crashes.  (The trouble with that is that you’d lose your count when the browser crashed!  You’d need to log the current count to a file or something like that.)

BTW, if you are thinking “you’ve just measured the working set size“, you’re exactly right! I think working set size is probably the best metric to use when evaluating memory consumption of a browser.  Unfortunately it’s hard to measure (as we’ve seen) and it is best measured via a  curve rather than a single number.

 A Simpler Methodology

I think memory sensitivity testing is an excellent way to gauge the memory efficiency of different browsers.  (In fact, the same methodology can be used for any kind of program, not just browsers.)

But the above experiment wasn’t easy:  it required a Linux machine, some non-trivial configuration of that machine that took me a while to get working, and at least 13 runs of each benchmark suite for each browser.  I understand that tech sites would be reluctant to do this kind of testing, especially when longer-running benchmark suites such as Dromaeo and Peacekeeper are involved.

A simpler alternative that would still be quite good would be to perform all the performance tests on several machines with different memory configurations.  For example, a good experimental setup might involve the following machines.

  • A fast desktop with 8GB or 16GB of RAM.
  • A mid-range laptop with 4GB of RAM.
  • A low-end netbook with 1GB or even 512MB of RAM.

This wouldn’t require nearly as many runs as full-scale memory sensitivity testing would.  It would avoid all the problems of cross-browser memory consumption comparisons:  difficult measurements, non-determinism, and adaptive behaviour.  It would avoid secondary metrics in favour of primary metrics.  And it would give results that are easy for anyone to understand.

(In some ways it’s even better than memory sensitivity testing because it involves real machines — a machine with a 3.4GHz i7-2600 CPU and only 128MiB of RAM isn’t a realistic configuration!)

I’d love it if tech sites started doing this.

MemShrink progress, week 31

Lots of good stuff happened this week in MemShrink-land.

Necko Buffer Cache

I removed the Necko buffer cache.  This cache used nsRecyclingAllocator to delay the freeing of up to 24 short-lived 32KB chunks (24 x 16KB on Mobile/B2G) in the hope that they could be reused soon.  The cache would fill up very quickly and the chunks wouldn’t be freed unless zero re-allocations occurred for 15 minutes.  This idea is to avoid malloc/free churn, but the re-allocations weren’t that frequent, and heap allocators like jemalloc tend to handle cases like this pretty well, so performance wasn’t affected noticeably.  Removing the cache has the following additional benefits.

  • nsRecyclingAllocator added a clownshoe-ish extra word to each chunk, which meant that the 32KB (or 16KB) allocations were being rounded up by jemalloc to 36KB (or 20KB), resulting in 96KB (24 x 4KB) of wasted memory.
  • This cache wasn’t covered by memory reporters, so about:memory’s “heap-unclassified” number has dropped by 864KB (24 x 36KB) on desktop and 480KB (24 x 20KB) on mobile.

I also removed the one other use of nsRecyclingAllocator in libjar, for which this recycling behaviour also had no noticeable effect.  This meant I could then remove nsRecyclingAllocator itself.  Taras Glek summarized things nicely:  “I’m happy to see placebos go away”.

Other Stuff

I gave a talk at the linux.conf.au Browser MiniConf entitled “Notes on Reducing Firefox’s Memory Consumption”, which got some attention on Slashdot.

Henrik Skupin reported that Ghostery 2.6.2 and 2.7beta2 have memory leaks (zombie compartments).  I contacted the authors today and they said they are looking into the problem, so hopefully we’ll see a fix soon.

Gian-Carlo Pascutto reworked the code that downloads the safe browsing database to use less memory, and to have a fallback if memory runs out.  This memory usage is transient and so the main benefit is that it prevents some out-of-memory crashes that were happening frequently.

Last week I mentioned bug 703427, which held up the possibility of a simple, big reduction in SQLite memory usage.  Marco Bonardo did some analysis, and unfortunately the patch caused large increases in the number of disk accesses, and so it won’t work.  A shame.

Kyle Huey fixed a zombie compartment that occurred when right-clicking on a single-line textbox.  The fun thing about this was that in only 3 hours and 35 minutes, the following events happened: the bug report was filed, the problem was confirmed by two people, the bug report was re-categorized into the appropriate component, a patch was posted, the patch was reviewed, the patch landed on mozilla-central, and the bug report was marked as fixed!  And approval for back-porting to Aurora was granted 8 hours later.  Not bad.  Kyle has also made progress on a more frequent zombie compartment caused by searching for text.

Jonathan Kew made the shaped-word caches (which are involved in text rendering) discard their data on memory pressure events.

Quote of the week

A commenter on my blog named jas said (the full comment is here):

a year ago, FF’s memory usage was about 10x what chrome was using in respect to the sites we were running…

so we have switched to chrome…

i just tested FF 9.0.1 against chrome, and it actually is running better than chrome in the memory department, which is good. but, it’s not good enough to make us switch back (running maybe 20% better in terms of memory). a tenfold difference would warrant a switch. in our instance, it was too little, too late.

but glad you are making improvements.

So that’s good, I guess?

I also like this comment from the aforementioned Slashdot thread!

Bug Counts

Here are the current bug counts.

  • P1: 24 (-3/+1)
  • P2: 131 (-8/+7)
  • P3: 69 (-1/+3)
  • Unprioritized: 3 (-3/+2)

That’s a net drop of two, largely because I went through and closed some P1 and P2 bugs that were stale or had been fixed elsewhere.

Converting a Chrome user to Firefox: a follow-up

I wrote yesterday about how I converted a relative of mine from a Chrome user to a Firefox user.  The post was picked up by the tech press including Tom’s Hardware and Conceivably Tech.  (Tom’s said I “described why getting users back from Chrome may nearly be impossible”, which I think is a laughable exaggeration of what I wrote.)

The good news is that the two major stumbling blocks I faced during the conversion are well on the way to being addressed.

  • The situation with third-party add-ons will be greatly improved in Firefox 8, which is scheduled for release in just a few days (2011-11-08).  The first time it runs, Firefox 8 will present the user with a window that lists all the installed add-ons, distinguishing between add-ons the user installed explicitly and third-party add-ons that they didn’t install explicitly.  The user will be asked to confirm which add-ons they want, and the third-party add-ons will be disabled by default.  The bug for this feature is here, and there is a follow-up bug here.
  • An “import history from Chrome” feature is being worked on right now.  Here is the feature page, a tracking bug, and  two dependent bugs.  The aim was for it to make Firefox 10, which is scheduled for release on 2012-01-31, but it looks like it might not make that release.  Hopefully it will make Firefox 11, which is scheduled for release on 2012-03-13.

Another point raised by commenters was that Chrome has a version of AdBlock Plus.  However, the Chrome version still has major shortcomings compared to the Firefox version.  This page states “We are currently working on providing the same experience for Google Chrome as what you are used to from Firefox. Please keep in mind that we are not there yet and much work still needs to be done. There are also known Google Chrome bugs and limitations that need to be resolved.”  This page lists the major shortcomings.  Maybe those shortcomings will be overcome in the future, but until they are, it’s not a reasonable comparison.

In conclusion, the point of my post yesterday was not to say “OMG Firefox is crap the sky is falling in”, but rather “here’s what happened when I tried this”.  I knew that the two obstacles I listed were being worked on, though I didn’t know the details.  (Many thanks to the commenters who filled me in.)  The fact that they are being worked on and/or have been fixed is rather encouraging.  It’s also worth noting that Firefox’s new rapid release calendar like these make it into the hands of ordinary users only 2 to 3 months after they are implemented.  With the old release calendar, these two improvements wouldn’t have made it into a release until mid-2012 or later.

Converting a Chrome user to Firefox

[Update: before commenting, you should probably read this follow-up post that clarifies certain things about this post.]

On my recent vacation I was staying with a family member, let’s call her Karen (not her real name).  She was a Google Chrome user, and I managed to convert her to a satisfied Firefox user.  Here’s what I learnt along the way.

tl;dr:

Bad things about the experience:

  • The third-party add-ons situation on Windows is awful.
  • We need a “import history from Chrome” feature.

Good things about the experience:

  • Mozilla’s non-profit nature is compelling, if you know about it.
  • AdBlock Plus is great.

The Initial Situation

Karen is a moderately sophisticated computer user. She knows what a browser is, but didn’t know how many there were, who made them, or any notable differences between them.

Her machine that is probably 2 or 3 years old, and runs Windows Vista.  She had used IE in the past (not sure which version) but didn’t like it, switched to Chrome at some point — she didn’t remember how or why — and found it to be much better.  She was running Chrome 14.0.835.202 (no, that’s not an IP address!) which was the latest stable version.

She also had Firefox 3.6.17 installed, but judging from the profile she hadn’t used it much — there was very little history.  She had the following Firefox add-ons installed:

  • Java Console 6.0.20 and 6.0.27.
  • The .NET Framework Assistant.
  • Some media player thing.
  • Some Norton “safe search” toolbar, and Symantec IPS, whatever that is.

(What is the Java Console?  What is the .NET Framework Assistant?  As far as I can tell they are (a) very common and (b) useless.)

I told her that I worked on Firefox and suggested that she try it and she was open to the idea.  I talked about the differences between Firefox and Chrome and some of my work on Firefox.  The thing that caught her attention most was that Mozilla is a non-profit organization.  She hadn’t known this and it appealed to her greatly — she said that browser speed and the non-profit nature were the two most important things to her.  She was also somewhat interested when I said that Firefox had an ad-blocking add-on.  At the end of the conversation, she agreed to let me install Firefox and make it the default browser.

Installing Firefox

I removed the existing Firefox profile manually — I wasn’t sure if this was necessary, but I definitely wanted a fresh profile — and then uninstalled Firefox through the Control Panel.  I then installed Firefox 7.0.1.  (BTW, I stayed with Karen for two weeks at this point, and I had deliberately waited until Firefox 7 was out before doing this because I knew it had much lower memory usage than Firefox 6.)

An unexpected thing was that the Firefox installer asked me to close all the other running programs;  it explained that this would mean that I wouldn’t have to reboot.  I’m used to running Firefox on Mac and Linux so I’m not used to this, but I’m familiar enough with Windows that I wasn’t totally surprised.  Still, it was annoying;  Karen had MS Word and some other programs open and I had to go ask her if I needed to save anything before closing them.  I realize this is Windows’ fault, not Firefox’s, but it was an obstacle.

Starting Firefox

When I started Firefox it asked me if I wanted to make it the default browser and I said yes.  (I explained to Karen how to switch the default browser back to Chrome if she was unhappy with Firefox.)

It also asked me if I wanted to import history/bookmarks/etc from IE.  But there was no equivalent for Chrome!  Karen had a ton of bookmarks in Chrome, but fortunately she said she only used a handful of them so I was able to copy them manually into Firefox’s bookmarks toolbar (which I had to make visible).  I’ve heard that someone is working on an “import from Chrome”  feature to Firefox but I don’t know what the status is.  We need it badly.

Once Firefox started, another unexpected thing was the state of the add-ons in the new profile.  The Symantec add-ons (including the ugly Norton toolbar) were present and enabled.  I had to disable them in about:addons;  I wanted to completely uninstall them but I couldn’t, the “uninstall” button just wasn’t present.  The Java Consoles and the media player were disabled because they were incompatible with 7.0.1, but I was also not able to  uninstall them.  This horrified me.  Is it a Windows-only behaviour?  Whatever the explanation, the default situation in a fresh install was that Firefox had several unnecessary, ugly additions, and it took some effort to remove them.  I’m really hoping that the add-on confirmation screen that has been added to Firefox 8 will help improve this situation, because this was the single worst part of the process.

I then tweaked the location of the home and reload buttons so they were in exactly the same position as in Chrome.  I probably didn’t need to do that, but  with those changes made Firefox’s UI looked very similar to Chrome’s, and I wanted things to be as comfortable for her as possible.

The best part of the process was when I installed AdBlock Plus.  With Karen watching, I visited nytimes.com in Chrome, and I had to skip past a video advertisement before even getting to the front page, and then the front page had heaps of ads.  Then I visited in Firefox — no video, no ads.  It was great!

Follow-up

A week or two later I sent Karen a follow-up email to check that everything was ok.  She said “All is well! The ad blocking is a great feature.”

So, Firefox has a new and happy user, but there were some obstacles along the way, and the outcome probably wouldn’t have been so good if Karen hadn’t had a Firefox expert to help her.