Understanding Heap Profiler

2,896 views
Skip to first unread message

C Snover

unread,
Jan 22, 2011, 7:18:17 PM1/22/11
to Google Chrome Developer Tools
Hi everyone,

I’m working on writing a short article on how to use the Memory
Timeline and Heap Snapshot tool in Google Chrome, since the
documentation at http://code.google.com/chrome/devtools/ is pretty
spartan and doesn’t really provide much useful information for people
that don’t already have an advanced knowledge of how V8’s memory
internals work (or memory management in general). Unfortunately, I’m
also coming at this from the viewpoint of someone that doesn’t
entirely “get it”, and I’m hoping that people can offer some
explanations that can help better my understanding of these features.

1. What exactly is being drilled down when going through the table?
For instance, if I expand the Array constructor, what am I looking at?
Are those a list of object types with properties that reference an
Array? Does “(closure)” mean that Array is being made available
through a closure in some other code? I’m just really not entirely
clear on these structures, and it is one of the main things I want to
make clear in my article.

2. What do the terms “(roots)” and “(global property)” mean in the
context of the heap snapshot table?

3. What, exactly, is a “(code)” object? From a brief skim of the
Chromium source, it looks like it is anything identified as being
IsCode, IsSharedFunctionInfo, or IsScript, but I don’t know what
exactly those are. My gut assumptions are that Code are blocks of JIT-
compiled code and Script is an uninterpreted chunk of script, but
those are mostly uneducated guesses. I have no clue what
SharedFunctionInfo would be. Information here would be appreciated.

Thanks in advance!

Regards,

Mikhail Naganov

unread,
Jan 24, 2011, 5:41:36 AM1/24/11
to google-chrome-...@googlegroups.com, goo...@zetafleet.com
Hi C Snover,

I would like to help you in your efforts. Answers are inline.

On Sun, Jan 23, 2011 at 03:18, C Snover <goo...@zetafleet.com> wrote:
> Hi everyone,
>
> I’m working on writing a short article on how to use the Memory
> Timeline and Heap Snapshot tool in Google Chrome, since the
> documentation at http://code.google.com/chrome/devtools/ is pretty
> spartan and doesn’t really provide much useful information for people
> that don’t already have an advanced knowledge of how V8’s memory
> internals work (or memory management in general). Unfortunately, I’m
> also coming at this from the viewpoint of someone that doesn’t
> entirely “get it”, and I’m hoping that people can offer some
> explanations that can help better my understanding of these features.
>
> 1. What exactly is being drilled down when going through the table?
> For instance, if I expand the Array constructor, what am I looking at?
> Are those a list of object types with properties that reference an
> Array? Does “(closure)” mean that Array is being made available
> through a closure in some other code? I’m just really not entirely
> clear on these structures, and it is one of the main things I want to
> make clear in my article.
>

Yes, you are looking at aggregated retainers. The number in the object
column indicates the number of references.
"(closures)" are functions closures, that's right.

> 2. What do the terms “(roots)” and “(global property)” mean in the
> context of the heap snapshot table?
>

(roots) are GC roots -- current stack, active V8 handle scopes,
compilation cache, global handles.
(global property) are special intermediate objects that stand between
a global object (e.g. window) and an object that is referenced from
it. E.g. if an object created using constructor A is held by a global
object, then a retaining path will look like this: [global] -> (global
property) -> A. Whereas in all other cases objects reference each
other directly.

> 3. What, exactly, is a “(code)” object? From a brief skim of the
> Chromium source, it looks like it is anything identified as being
> IsCode, IsSharedFunctionInfo, or IsScript, but I don’t know what
> exactly those are. My gut assumptions are that Code are blocks of JIT-
> compiled code and Script is an uninterpreted chunk of script, but
> those are mostly uneducated guesses. I have no clue what
> SharedFunctionInfo would be. Information here would be appreciated.
>

(code) is everything related to compiled code. Script is like a
function but corresponds to a script body. SharedFunctionInfos are
objects that stand between functions and compiled code. Functions are
usually have a context, while SFIs are context-less. So several
functions of different contexts can share their common data in a
single SFI. SFI holds a link to the compiled code.

> Thanks in advance!
>
> Regards,
>

C Snover

unread,
Jan 26, 2011, 10:20:44 PM1/26/11
to Google Chrome Developer Tools
Hi Mikhail,

Thanks very much for your help. Bear with me, as I have a couple of
follow-ups, below. (Also, I accidentally replied directly to you
instead of to the list; sorry about that.)

On Jan 24, 4:41 am, Mikhail Naganov <mnaga...@chromium.org> wrote:
> (roots) are GC roots -- current stack, active V8 handle scopes,
> compilation cache, global handles.

So, could these be likened to references to objects from within the
engine itself?

> (global property) are special intermediate objects that stand between
> a global object (e.g. window) and an object that is referenced from
> it.

Why is this done?

> (code) is everything related to compiled code. Script is like a
> function but corresponds to a script body. SharedFunctionInfos are
> objects that stand between functions and compiled code. Functions are
> usually have a context, while SFIs are context-less. So several
> functions of different contexts can share their common data in a
> single SFI. SFI holds a link to the compiled code.

So, just to confirm I understand:

1. Script is any code inside a <script> block that is not part of a
function definition, e.g. <script>var foo = 42;</script>
2. SFI can be roughly considered to be a pointer to the compiled code
for a function that might be referenced in several different contexts
(e.g. var foo = function () {}, bar = {}; bar.foo = foo; both point to
the same SFI but have a different context)
3. a Function is a thin wrapper to an SFI that mostly just contains
additional information about the context that the SFI code executes in

Is that correct?

Finally, where does the source JavaScript fit in here? Is that
considered “code object” since it’s compilable/interpretable code, or
does that go in the “data object” bin since it’s uncompiled source?

Thanks again,

Mikhail Naganov

unread,
Jan 27, 2011, 8:29:33 AM1/27/11
to google-chrome-...@googlegroups.com, goo...@zetafleet.com
On Thu, Jan 27, 2011 at 06:20, C Snover <goo...@zetafleet.com> wrote:
> Hi Mikhail,
>
> Thanks very much for your help. Bear with me, as I have a couple of
> follow-ups, below. (Also, I accidentally replied directly to you
> instead of to the list; sorry about that.)
>
> On Jan 24, 4:41 am, Mikhail Naganov <mnaga...@chromium.org> wrote:
>> (roots) are GC roots -- current stack, active V8 handle scopes,
>> compilation cache, global handles.
>
> So, could these be likened to references to objects from within the
> engine itself?
>

Not sure what do you mean by the "references ... from within the
engine". All references are exist within the engine. If you mean
whether there can be references created by the engine for its sole
purposes -- yes, sort of. E.g. the engine has caches that reference
objects, but all such references are of a "weak" kind -- they will not
prevent an object from collection, having that there are no "strong"
references.

>> (global property) are special intermediate objects that stand between
>> a global object (e.g. window) and an object that is referenced from
>> it.
>
> Why is this done?
>

For performance. Global objects are modified frequently, and property
access optimizations that do a good job for non-global objects
(described here
http://code.google.com/apis/v8/design.html#prop_access), are not
applicable for globals. So, generated code always refers to "global
property cell"
objects, which hold real values.

>> (code) is everything related to compiled code. Script is like a
>> function but corresponds to a script body. SharedFunctionInfos are
>> objects that stand between functions and compiled code. Functions are
>> usually have a context, while SFIs are context-less. So several
>> functions of different contexts can share their common data in a
>> single SFI. SFI holds a link to the compiled code.
>
> So, just to confirm I understand:
>
> 1. Script is any code inside a <script> block that is not part of a
> function definition, e.g. <script>var foo = 42;</script>

Right.

> 2. SFI can be roughly considered to be a pointer to the compiled code
> for a function that might be referenced in several different contexts
> (e.g. var foo = function () {}, bar = {}; bar.foo = foo; both point to
> the same SFI but have a different context)

By the "context" I mean function's lexical scope. E.g. if I define the
following function:

function createAdder(n) {
return function adder(x) { return n + x; }
}
var add3 = createAdder(3);
var add5 = createAdder(5);

The compiled code for the "adder" function is the same, but for the "add3"
the value of "n" is 3, while for "add5" "n" is 5. That means, "add3" and "add5"
refer to different Function objects, but both of them refer the same SFI.

> 3. a Function is a thin wrapper to an SFI that mostly just contains
> additional information about the context that the SFI code executes in
>

Yes, see above. Function refers to SFI and to the map of variable bindings.

> Is that correct?
>
> Finally, where does the source JavaScript fit in here? Is that
> considered “code object” since it’s compilable/interpretable code, or
> does that go in the “data object” bin since it’s uncompiled source?
>

No. JS source code is stored in strings.

BTW, thanks for the bug report about sorting.

> Thanks again,
>

C Snover

unread,
Jan 27, 2011, 12:59:07 PM1/27/11
to Google Chrome Developer Tools
On Jan 27, 7:29 am, Mikhail Naganov <mnaga...@chromium.org> wrote:
> > On Jan 24, 4:41 am, Mikhail Naganov <mnaga...@chromium.org> wrote:
> >> (roots) are GC roots -- current stack, active V8 handle scopes,
> >> compilation cache, global handles.
>
> > So, could these be likened to references to objects from within the
> > engine itself?
>
> Not sure what do you mean by the "references ... from within the
> engine". All references are exist within the engine. If you mean
> whether there can be references created by the engine for its sole
> purposes -- yes, sort of. E.g. the engine has caches that reference
> objects, but all such references are of a "weak" kind -- they will not
> prevent an object from collection, having that there are no "strong"
> references.

OK. I completely misunderstood what GC roots were. I found an article
at http://www.artima.com/insidejvm/ed2/gcP.html that describes them,
so this is much clearer now.

> > 2. SFI can be roughly considered to be a pointer to the compiled code
> > for a function that might be referenced in several different contexts
> > (e.g. var foo = function () {}, bar = {}; bar.foo = foo; both point to
> > the same SFI but have a different context)
>
> By the "context" I mean function's lexical scope. E.g. if I define the
> following function:
>
> function createAdder(n) {
> return function adder(x) { return n + x; }}
>
> var add3 = createAdder(3);
> var add5 = createAdder(5);
>
> The compiled code for the "adder" function is the same, but for the "add3"
> the value of "n" is 3, while for "add5" "n" is 5. That means, "add3" and "add5"
> refer to different Function objects, but both of them refer the same SFI.

Got it. This is very clear now. Thanks for the explanation. :)

> BTW, thanks for the bug report about sorting.

Any time. :)

I think this should be everything I need to finish up; I’ll post a
link here when the article is done. Hopefully it will be accurate and
useful. :)

Cheers,

Mikhail Naganov

unread,
Jan 27, 2011, 1:15:24 PM1/27/11
to google-chrome-...@googlegroups.com
On Thu, Jan 27, 2011 at 20:59, C Snover <goo...@zetafleet.com> wrote:
> On Jan 27, 7:29 am, Mikhail Naganov <mnaga...@chromium.org> wrote:
>> > On Jan 24, 4:41 am, Mikhail Naganov <mnaga...@chromium.org> wrote:
>> >> (roots) are GC roots -- current stack, active V8 handle scopes,
>> >> compilation cache, global handles.
>>
>> > So, could these be likened to references to objects from within the
>> > engine itself?
>>
>> Not sure what do you mean by the "references ... from within the
>> engine". All references are exist within the engine. If you mean
>> whether there can be references created by the engine for its sole
>> purposes -- yes, sort of. E.g. the engine has caches that reference
>> objects, but all such references are of a "weak" kind -- they will not
>> prevent an object from collection, having that there are no "strong"
>> references.
>
> OK. I completely misunderstood what GC roots were. I found an article
> at http://www.artima.com/insidejvm/ed2/gcP.html that describes them,
> so this is much clearer now.
>

You may also consider this article which talks specifically about V8 GC:
http://developer.palm.com/index.php?option=com_content&view=article&id=2064

>> > 2. SFI can be roughly considered to be a pointer to the compiled code
>> > for a function that might be referenced in several different contexts
>> > (e.g. var foo = function () {}, bar = {}; bar.foo = foo; both point to
>> > the same SFI but have a different context)
>>
>> By the "context" I mean function's lexical scope. E.g. if I define the
>> following function:
>>
>> function createAdder(n) {
>>   return function adder(x) { return n + x; }}
>>
>> var add3 = createAdder(3);
>> var add5 = createAdder(5);
>>
>> The compiled code for the "adder" function is the same, but for the "add3"
>> the value of "n" is 3, while for "add5" "n" is 5. That means, "add3" and "add5"
>> refer to different Function objects, but both of them refer the same SFI.
>
> Got it. This is very clear now. Thanks for the explanation. :)
>
>> BTW, thanks for the bug report about sorting.
>
> Any time. :)
>
> I think this should be everything I need to finish up; I’ll post a
> link here when the article is done. Hopefully it will be accurate and
> useful. :)
>

Looking forward to see it!

> Cheers,
>

C Snover

unread,
Jan 27, 2011, 1:56:12 PM1/27/11
to Google Chrome Developer Tools
Hi everyone,

I’ve posted my article at http://zetafleet.com/blog/google-chromes-heap-profiler-and-memory-timeline.
If there are any gross inaccuracies or things that you see that should
be clarified, please let me know at once—I’d like to make sure I am
not feeding bad information to anyone. :)

Cheers,

Mikhail Naganov

unread,
Jan 28, 2011, 5:47:59 AM1/28/11
to google-chrome-...@googlegroups.com, goo...@zetafleet.com
Thanks for your post! We are working on improving the heap profiler,
and your requests will be soon addressed.

Davit Barbakadze

unread,
Feb 27, 2011, 1:07:49 PM2/27/11
to Google Chrome Developer Tools
Really looking forward to see an improved Heap Profiler, which is
really lacking support for tracking down specific objects. Doesn't
look like helpful solution at the moment, although definitely is
unique.


On Jan 28, 2:47 pm, Mikhail Naganov <mnaga...@chromium.org> wrote:
> Thanks for your post! We are working on improving theheapprofiler,
> and your requests will be soon addressed.
>
>
>
>
>
>
>
> On Thu, Jan 27, 2011 at 21:56, C Snover <goo...@zetafleet.com> wrote:
> > Hi everyone,
>
> > I’ve posted my article athttp://zetafleet.com/blog/google-chromes-heap-profiler-and-memory-tim....

Peter Reinhardt

unread,
Mar 8, 2012, 2:09:57 AM3/8/12
to google-chrome-...@googlegroups.com
Hi,

Thanks for the article C Snover, super helpful. I've found the heap profiler to be really useful in tracking down memory consumption problems in our one-page web app.

I just posted an article about how we use the heap profiler to answer the two big questions we had as developers: (1) how big are my objects? and (2) when I delete them, are they really gone? which has a pre-requisite question (3) how do I find my objects in the various heap profiler views?


I hope it's useful, and I would love any feedback or suggestions you have about better ways to answer these memory usage questions. We're really looking forward to improvements in the profiler that make these questions easier to answer :)

Thanks,
Peter
Reply all
Reply to author
Forward
0 new messages