I have recently spent some time hunting down memory leaks in Firebug and the most successful way I have found so far has been analyzing CC (Cycle Collector) object graph - graph of objects that are cycle collected.
The particular memory leak I have been looking for is called a zombie compartment. In my case, there is a document living in the memory even if the parent tab has been closed long time ago. Something is still referencing that document object so, it can't be released. The goal here is usually to find that referent. And this is when the CC heap debugging comes to rescue.
The rest of this post describes my extension CCDump that allows to dynamically analyze CC object graph.
CC heap dump log can be created manually using the following script (you can evaluate it in Firefox Error Console).
A file, something like: cc-edges-1.7104.log is created and path to it logged into the Error Console. This file contains text representation of the entire graph and you can use any text editor to search it.
Manual creation and search is tedious and you can easily spent hours and hours by repeating manual steps: open Firefox, reproduce a memory leak, execute the script to get the log, open the text file, search for zombie document, search for related objects, etc. - without any satisfying results.
That's why I decided to automate the entire process. Thanks to Olli Pettay who implemented a new API (introduced in Firefox 13, current Nightly) that allows to dynamically analyze the CC object graph from within an extension.
I implemented a bootstrapped (restart-less) extension that can be installed at the moment when you are experiencing a zombie compartment in your browser session - and immediately (without restart) analyze the current CC graph.
You can also use
about:memory I order to see zombie compartments.
CCDump extension can be used to search within the object graph and execute queries to get the information you need.
After you install the extension, open:
You should see something as follows:
You mostly want to start by clicking on Run CC Analysis button in the Home tab. After you do it, Firefox cycle collector runs three times to clean up garbage and consequently once, with a listener, to collect entire CC graph of objects in the memory. The result object graph is immediately displayed as a table where each entry represents an object.
Every object has a context menu, just click the black triangle next to the green object label. There are three ways how to query the graph.
- Show Details - see detailed information about the object
- Show Roots - get roots that keep this object in the memory
- Show Graph - get all objects that are directly or indirectly related to the object (the result is displayed as an expandable tree).
Show Graph allows to dramatically reduce the object graph to see only related objects and search further only in the sub-graph result.
You can also search the graph. Use a search box located at the top right corner. Note that if there is a string in the box the search runs automatically just after analysis (I am typically keeping
nsDocument text in the box).
There are some options:
- Find Zombie Documents - search for objects with
nsDocumentstring in the name (i.e. for zombie content documents)
- Find Zombie HTTP Elements - search for objects with
httpstring in the name (i.e. for zombie content nodes)
- Clear Search Results - trash the current search results and show the original table with entire graph.
- Case Sensitive - case sensitive search
- Use Regular Expression - you can also use regular expression to search the graph
The next screenshot shows object detail view:
- address unique hexadecimal address of the object. Always clickable thorough the UI
- refcount number of referents
- gcmarked if false CC is OK with freeing the object
- root if true the object is a root
- edges array of objects referenced by this object
- owners array of parent objects referencing this object
Where edges and owners represent relations in the graph.
Any feedback is welcome!
What could be yet improved in the UI?
What other queries could be made to the graph?
What other information in the CC graph would help to find and fix a memory leak?
My typical scenario when hunting down zombie compartments looks briefly as follows:
- Run the browser, reproduce a memory leak
Run CC Analysisto get the current object graph
- Search for
nsDocumentto see a zombie document object
- Show Graph for the zombie document
- Search within the result graph for objects that keep it alive
The challenge is usually successful identification of an object in the graph and matching it with the corresponding object in the source code. Having more identity information would certainly help. Anyway, this problem should be dramatically reduced as soon as Bug 722749 i fixed - provide information about where JS object was allocated (source URL & line number).
Related resources you might find useful: