Update 2007-11-06: see also my more recent post on this topic, Firefox memory usage and memory leak news, from September 2007.
One of the more common complaints about Firefox 1.5 was that it leaked a lot of memory. I don't know how often these leaks were severe enough to cause noticeable slowdowns or thrashing, but enough Firefox users seem to care about memory leaks that I thought I'd post something about what we've done and what we're doing.
Two memory leak bugs were fixed in Firefox 184.108.40.206, released earlier this week:
- 316775 - Leak when selecting.
- 317478 - Leaks due to global scope polluter being removed from not enough (?) prototype chains.
In addition, the following memory leaks have been fixed on the trunk since the branch point for Firefox 1.5:
- 241518 - Calling addEventListener with a closure holding a content node leaks the document. (Many Greasemonkey scripts use addEventListener, and they each live within implied closures. Otherwise, this leak pattern isn't too common, mostly because Internet Explorer 6 leaks under the same circumstances.)
- 321283 - Using Find causes documents to leak.
- 315708 - Should release found link and current window object from nsTypeAheadFind.cpp.
- 315951 - Unknown content type dialog leaks domwindow.
- 319123 - Leak with contentsink-parser-dtd cycle involving document.write().
- 323441 - Memory leak if a site sets location and then document.writes (e.g. when visiting www.economist.com).
- 323377 - Lots of leaks in nsInternetSearchService.
- 323532 - Leak when using history autocomplete.
- 315427 - Bad nullcheck in nsXULPrototypeElement::ReleaseSubtree, causing the Options window to leak if the remembered panel is the cache panel.
- 323534 - CreateTreeWalker can cause leaks due to cycles created by closures.
The trunk seems close to not leaking huge object graphs during my typical browsing sessions (YMMV). The only big leak I still see all the time is a leak at Gmail. The leak might be related to the "unused XMLHttpRequest" leak that David Baron is working on, or it might not -- when I asked whether Gmail is considering working around the "unused XMLHttpRequest" leak bug, a Gmail coder said he didn't think Gmail created any XMLHttpRequest objects it didn't use.
David Baron's leak-gauge has been allowing more people to test for large memory leaks with their own browsing habits, extensions, and favorite sites. At least 19 people filed 30 memory leak bug reports found using leak-gauge, accounting for more than half of the memory leak bug reports (and most of the memory leak bug reporters) since its introduction. The bug reports look pretty useful, and are definitely more useful than general complaints about high memory usage after using Firefox for a few hours.
If you're still suffering a lot from memory leaks in Firefox 220.127.116.11 and/or want to help find memory leak bugs, head over to The Burning Edge and try out a trunk build. If you prefer to stick with stable versions of Firefox, don't worry -- many of the fixes that are currently only on the trunk will be included in the next scheduled update (currently planned to be called Firefox 18.104.22.168 and released in March), most of them will be included in Firefox 2, and all of them will be included in Firefox 3.
Leaks in extensions
Recognizing that memory leaks aren't always due to bugs in Firefox itself, Steve England and others have tested popular Firefox extensions for memory leaks. They found that Session saver, NoScript, IE Tab, and the combination of FlashGot and Filterset.G Updater cause leaks.
Giorgio Maone, the author of NoScript and FlashGot, has already fixed the biggest leak in NoScript thanks to Steve's bug report. He is now working on threading issues in FlashGot that prevent debugging and might be responsible for the leaks. Authors of the other extensions haven't been as fast to fix their leaks.
I also fixed several minor memory leaks in my own extensions recently, some found through code inspection and some found using leak-gauge. Search Keys 0.7.2 and below kept parts of search result pages alive for the lifetime of the window due to an unintentionally global variable (a missing "var"). Thumbs 0.6.1 and below kept the DOMWindow for the page Thumbs was last used on alive until shutdown.