Using Heap Profiler to track memory leaks

3,448 views
Skip to first unread message

matad...@googlemail.com

unread,
Jan 15, 2013, 10:47:19 AM1/15/13
to google-chrome-...@googlegroups.com
Hi

We're having a hard time tracking memory leaks in our application using the heap profiler. I emailed Addy who responded as below. I'd appreciate if anyone can help follow up

We're having real difficulty using the comparisons view to correlate back to the root reference. I appreciate your very busy however if you can provide any quick guidance I'd really appreciate it.  From the help I see 
 various screenshots however they seem to relate to an older version perhaps?
https://developers.google.com/chrome-developer-tools/docs/heap-profiling
e.g. the section on the summary view mentions a label "Click on an object to show retaining paths" however this isn't present on my version. Similarly the screenshots have icons for "Profiles" however I only see the labels

from Addy

Your last note is correct. The current version of the heap profiling documentation is out of date, but we're working on rewriting all of the docs for a push this month. The current version of the heap profiler will always trace to window objects and expands to display the retained tree when you select an object in either the summary or comparison views. 
Are you using Canary for your comparisons? Note that depending on the type of object, there may be no retained path information displayed (e.g if no information is available for a parent object, you need to dig down/expand into its children in order to view retained path info). 


I've attached the screenshot of the comparison view we used however when we drill into the various DOM nodes references ( i.e. those deltas + ) we can't see any retaining path

Thanks 
ChromeHeapProfilerComparisonScreenshot.docx

Ilya Tikhonovsky

unread,
Jan 15, 2013, 10:50:05 AM1/15/13
to matad...@googlemail.com, Google Chrome Developer Tools
There is a different approach.
If you have a scenario for a leak you can use three snapshot technique.


Regards,
Tim.

Ilya Tikhonovsky

unread,
Jan 15, 2013, 10:57:04 AM1/15/13
to matadamson, Google Chrome Developer Tools
In summary view the objects are grouped by class name.
You need to select an instance after that the bottom pane will show you the retainers for this particular object.

Regards,
Tim.

matad...@googlemail.com

unread,
Jan 15, 2013, 4:09:41 PM1/15/13
to google-chrome-...@googlegroups.com, matadamson
Added further updates

Actually I don't know is it leaked or not. Comparison view could help you only if you know that there should be no objects of this class objects at all.

If the background of an object is yellow then usually it could be accessed from javascript.
You need to expand all the elements in the retainers pane up to window object.
The reversed sequence of the objects in the tree will lead you to the object.

Regards,
Tim.


9:00 PM (7 minutes ago)

to Ilya 
Confused then as I thought the comparison view with entries where delta is + must indicated there leaked elements i.e. if you repeat the same action between two snap shots any additional items in the heap are leaks?

If I expand the array element in question I don't see the window object at the end? 

How would you diagnose this further?

Ilya Tikhonovsky

unread,
Jan 15, 2013, 10:15:30 PM1/15/13
to Matt Adamson, Google Chrome Developer Tools, Addy Osmani
Comparison view usually doesn't help if you run a leaking action only once between snapshots. A sample:

Imagine that you run the next script from time to time.

var anArrayThatMakesALeak[];
var aWorkingObject;

function AnObject()
{
  this._data = "a sting";
}

function testFunction()
{
  aWorkingObject = new AnObject();
  anArrayThatMakesALeak.push(anObject);
}

after the first run you will see in the first snapshot Summary view the one AnObject object with 2 retainers. window and anArrayThatMakesALeak.
Suppose that this object is not a leak because page need an working object for other code.
after the second run in the second snapshot Summary view you will see two objects. The first with one retainer anArrayThatMakesALeak 
(it became a leak because we forgot to remove it from the array) , the second with two retainers. The second object is ok because we need a working object.
The comparison will show you only the second instance which is not a leak.
The leaked object will be hidden by Comparison view because it exists in the both snapshots.

However if you do the leaking action N times between these two snapshots then you will see N new objects in Comparison view.
If you definitely know that it should be only one which was made by the last action then you have a leak.

Regards,
Tim.

Matt Adamson

unread,
Jan 16, 2013, 6:52:33 AM1/16/13
to Ilya Tikhonovsky, Google Chrome Developer Tools, Addy Osmani
Thanks Illya

Few points

1) Going back to my earlier comment to Addy on not being able to view the retaining path for the detached nodes how do you suggest we see them? Addy indicated the documentation was out of date
2) I presume you mean repeat the test a number of times e.g. 5 and then use the comparison view between the initial snapshot and last e.g. 1 and 5. I did this and noticed a number of DOM nodes where some are highlighted in red and indicated as a "Detached DOM tree" however although these nodes are familiar to our applications it's not obvious why they should be retained. e.g. one is a standard Dojo widget which we see destroyed in our logs 

Yury Semikhatsky

unread,
Jan 16, 2013, 7:38:35 AM1/16/13
to Matt Adamson, Ilya Tikhonovsky, Google Chrome Developer Tools, Addy Osmani
On Wed, Jan 16, 2013 at 3:52 PM, Matt Adamson <matad...@googlemail.com> wrote:
Thanks Illya

Few points

1) Going back to my earlier comment to Addy on not being able to view the retaining path for the detached nodes how do you suggest we see them? Addy indicated the documentation was out of date

On the screenshot you sent you selected HTMLImageElement constructor which groups all instances with such constructor and to see their retainers tree you should select particular instance as Ilya suggested. Doesn't it work for you?
 
2) I presume you mean repeat the test a number of times e.g. 5 and then use the comparison view between the initial snapshot and last e.g. 1 and 5.
Not quite. The idea is to use the summary view but leave there only objects allocated in some time interval. To do so you take snapshot 1, then do some actions which is expected to allocate some objects, then you take second snapshot to mark the end of the interval where the objects of interest were allocated, do some actions that should result in garbage collection of the objects allocated earlier and then take snapshot 3. After that select summary view of snapshot 3 and chose to show only "Objects allocated between snapshots 1 and 2". If there are no leaks the summary view should be empty.

 
I did this and noticed a number of DOM nodes where some are highlighted in red and indicated as a "Detached DOM tree" however although these nodes are familiar to our applications it's not obvious why they should be retained. e.g. one is a standard Dojo widget which we see destroyed in our logs 


Red nodes don't have direct references from javascript to them. But the nodes are a part of some detached DOM tree which contain other nodes some of which are referenced from javascript and thus prevent the whole DOM tree from beeing GCed. You should look for yellow nodes in the same detached dom tree to find references from javascript. Yellow nodes are those that do have references from javascript.

Yury

Matt Adamson

unread,
Jan 16, 2013, 8:47:03 AM1/16/13
to Yury Semikhatsky, Ilya Tikhonovsky, Google Chrome Developer Tools, Addy Osmani
Thanks

1) Going back to my earlier comment to Addy on not being able to view the retaining path for the detached nodes how do you suggest we see them? Addy indicated the documentation was out of date

On the screenshot you sent you selected HTMLImageElement constructor which groups all instances with such constructor and to see their retainers tree you should select particular instance as Ilya suggested. Doesn't it work for you?
You can select a particular element in the retaining tree however it doesn't indicate the full path to it's root object as the online documentation shows ( which Addy said was out of date ) 

2) I presume you mean repeat the test a number of times e.g. 5 and then use the comparison view between the initial snapshot and last e.g. 1 and 5.
Not quite. The idea is to use the summary view but leave there only objects allocated in some time interval. To do so you take snapshot 1, then do some actions which is expected to allocate some objects, then you take second snapshot to mark the end of the interval where the objects of interest were allocated, do some actions that should result in garbage collection of the objects allocated earlier and then take snapshot 3. After that select summary view of snapshot 3 and chose to show only "Objects allocated between snapshots 1 and 2". If there are no leaks the summary view should be empty.
This isn't really possible i.e. we click on a menu item which refreshes an inner div ( a Dojo content pane ).  The div is loaded with the value from another HTML page to present a list. The snapshot 1 in your example above would be when the inner div is loaded with the list. However you have to refresh the list again to destroy and recreate so in relation to "do some actions that should result in garbage collection of the objects allocated earlier" we have to reload the div which should destroy the inner div objects however it also reloads immediately. Are you suggesting we add a link to the site perhaps to try and do an internal clean up of the div and then take snapshot 2?

Red nodes don't have direct references from javascript to them. But the nodes are a part of some detached DOM tree which contain other nodes some of which are referenced from javascript and thus prevent the whole DOM tree from beeing GCed. You should look for yellow nodes in the same detached dom tree to find references from javascript. Yellow nodes are those that do have references from javascript.

Thanks so can we take any further action with respect to red nodes if we only concentrate on yellow nodes?

Ilya Tikhonovsky

unread,
Jan 16, 2013, 8:59:13 AM1/16/13
to Matt Adamson, Yury Semikhatsky, Google Chrome Developer Tools, Addy Osmani
On Wed, Jan 16, 2013 at 5:47 PM, Matt Adamson <matad...@googlemail.com> wrote:
Thanks

1) Going back to my earlier comment to Addy on not being able to view the retaining path for the detached nodes how do you suggest we see them? Addy indicated the documentation was out of date

On the screenshot you sent you selected HTMLImageElement constructor which groups all instances with such constructor and to see their retainers tree you should select particular instance as Ilya suggested. Doesn't it work for you?
You can select a particular element in the retaining tree however it doesn't indicate the full path to it's root object as the online documentation shows ( which Addy said was out of date ) 

Yes. The documentation is out of date. We do not calculate the full retaining path as a string. The pane with list of retaining paths were replaced with retainer tree pane.
 

2) I presume you mean repeat the test a number of times e.g. 5 and then use the comparison view between the initial snapshot and last e.g. 1 and 5.
Not quite. The idea is to use the summary view but leave there only objects allocated in some time interval. To do so you take snapshot 1, then do some actions which is expected to allocate some objects, then you take second snapshot to mark the end of the interval where the objects of interest were allocated, do some actions that should result in garbage collection of the objects allocated earlier and then take snapshot 3. After that select summary view of snapshot 3 and chose to show only "Objects allocated between snapshots 1 and 2". If there are no leaks the summary view should be empty.
This isn't really possible i.e. we click on a menu item which refreshes an inner div ( a Dojo content pane ).  The div is loaded with the value from another HTML page to present a list. The snapshot 1 in your example above would be when the inner div is loaded with the list. However you have to refresh the list again to destroy and recreate so in relation to "do some actions that should result in garbage collection of the objects allocated earlier" we have to reload the div which should destroy the inner div objects however it also reloads immediately. Are you suggesting we add a link to the site perhaps to try and do an internal clean up of the div and then take snapshot 2?

The three snapshot schema works fine with this situation. You don't need to cleanup your list manually.
 

Red nodes don't have direct references from javascript to them. But the nodes are a part of some detached DOM tree which contain other nodes some of which are referenced from javascript and thus prevent the whole DOM tree from beeing GCed. You should look for yellow nodes in the same detached dom tree to find references from javascript. Yellow nodes are those that do have references from javascript.

Thanks so can we take any further action with respect to red nodes if we only concentrate on yellow nodes?

yep. 



Regards,
Tim.

Matt Adamson

unread,
Jan 16, 2013, 9:20:37 AM1/16/13
to Ilya Tikhonovsky, Yury Semikhatsky, Google Chrome Developer Tools, Addy Osmani
1) Going back to my earlier comment to Addy on not being able to view the retaining path for the detached nodes how do you suggest we see them? Addy indicated the documentation was out of date

On the screenshot you sent you selected HTMLImageElement constructor which groups all instances with such constructor and to see their retainers tree you should select particular instance as Ilya suggested. Doesn't it work for you?
You can select a particular element in the retaining tree however it doesn't indicate the full path to it's root object as the online documentation shows ( which Addy said was out of date ) 
Yes. The documentation is out of date. We do not calculate the full retaining path as a string. The pane with list of retaining paths were replaced with retainer tree pane.
In this case then the retaining pane tree view shows more than one element as the root sometimes. e.g. in the screen shot attached. Is this implying that the grid function has a reference to this DOM node indirectly? If this is the case what is reference the grid function to stop it being garbage collected? This can't be seen from the summary view output as far as I can tell


2) I presume you mean repeat the test a number of times e.g. 5 and then use the comparison view between the initial snapshot and last e.g. 1 and 5.
Not quite. The idea is to use the summary view but leave there only objects allocated in some time interval. To do so you take snapshot 1, then do some actions which is expected to allocate some objects, then you take second snapshot to mark the end of the interval where the objects of interest were allocated, do some actions that should result in garbage collection of the objects allocated earlier and then take snapshot 3. After that select summary view of snapshot 3 and chose to show only "Objects allocated between snapshots 1 and 2". If there are no leaks the summary view should be empty.
This isn't really possible i.e. we click on a menu item which refreshes an inner div ( a Dojo content pane ).  The div is loaded with the value from another HTML page to present a list. The snapshot 1 in your example above would be when the inner div is loaded with the list. However you have to refresh the list again to destroy and recreate so in relation to "do some actions that should result in garbage collection of the objects allocated earlier" we have to reload the div which should destroy the inner div objects however it also reloads immediately. Are you suggesting we add a link to the site perhaps to try and do an internal clean up of the div and then take snapshot 2?
The three snapshot schema works fine with this situation. You don't need to cleanup your list manually.
 
In that case I did something similar in the screenshot attached however it's numbered 4 - 6 instead of 1-3. 

4 - Taken before the inner div was loaded i.e. when we expect DOM nodes to be initially loaded and leaked
5 - Taken when the inner div was loaded where objects were allocated.
6 - Taken after the inner div was reloaded where objects from 4 should have been destroyed and deallocated and new objects created when the inner div refreshed

Matt Adamson

unread,
Jan 16, 2013, 9:44:33 AM1/16/13
to Ilya Tikhonovsky, Yury Semikhatsky, Google Chrome Developer Tools, Addy Osmani
With attached file ChromeHeapProfilerComparisonScreenshots-4.docx
ChromeHeapProfilerComparisonScreenshots-4.docx

Yury Semikhatsky

unread,
Jan 16, 2013, 10:19:01 AM1/16/13
to Matt Adamson, Ilya Tikhonovsky, Google Chrome Developer Tools, Addy Osmani
On Wed, Jan 16, 2013 at 6:44 PM, Matt Adamson <matad...@googlemail.com> wrote:
With attached file ChromeHeapProfilerComparisonScreenshots-4.docx


On Wed, Jan 16, 2013 at 2:20 PM, Matt Adamson <matad...@googlemail.com> wrote:
1) Going back to my earlier comment to Addy on not being able to view the retaining path for the detached nodes how do you suggest we see them? Addy indicated the documentation was out of date

On the screenshot you sent you selected HTMLImageElement constructor which groups all instances with such constructor and to see their retainers tree you should select particular instance as Ilya suggested. Doesn't it work for you?
You can select a particular element in the retaining tree however it doesn't indicate the full path to it's root object as the online documentation shows ( which Addy said was out of date ) 
Yes. The documentation is out of date. We do not calculate the full retaining path as a string. The pane with list of retaining paths were replaced with retainer tree pane.
In this case then the retaining pane tree view shows more than one element as the root sometimes. e.g. in the screen shot attached.
The root entries in the retaining tree view are the entities that have references to the selected object. In this case the object is an element in some Array and an element in a Detached DOM tree. The retainers are sorted by their proximity to the global object(Window) so that the closest one goes first. 

 
Is this implying that the grid function has a reference to this DOM node indirectly?
Yes. You see the path from 'grid' variable to the selected HTMLDivElement .
 
If this is the case what is reference the grid function to stop it being garbage collected?
I'm not sure 'grid' is a function it is just a variable with such name inside some anonymous function and as you can see in the expanded path the object has field/variable with name 'store' which is the next link on the retaining path.

Ilya Tikhonovsky

unread,
Jan 16, 2013, 10:19:05 AM1/16/13
to Matt Adamson, Yury Semikhatsky, Google Chrome Developer Tools, Addy Osmani
Usually we start investigation from the first retainer because all the retainers are sorted by the distance column. (distance to window object)
And the retainer with smallest distance usually is the main candidate.

You need to discover the reason why the retainer is keeping the reference to the object.

In your case you need to understand why the Array keeps the reference to the object.
Or why the array's retainer keeps the array alive etc.

We could not help you in this investigation because it is your code and we have no idea what it is doing :) 

Regards,
Tim.

Addy Osmani

unread,
Jan 16, 2013, 10:43:06 AM1/16/13
to Ilya Tikhonovsky, Yury Semikhatsky, Google Chrome Developer Tools, Matt Adamson
Ilya, Yury - thanks so much for taking the time to help out with Matt's questions. We're going to actively
make an effort to better capture your comments from this discussion in the profiler docs. 

duo...@gmail.com

unread,
Feb 21, 2013, 11:56:34 AM2/21/13
to google-chrome-...@googlegroups.com, Ilya Tikhonovsky, Yury Semikhatsky, Matt Adamson
Hi Addy, I was thinking about writing a tool to visualize the retaining tree, and help to find path to Global/GCRoots. Could you please tell me about format of the saved heap dump file. Thank you very much!
Reply all
Reply to author
Forward
0 new messages