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.
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 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?
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?
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.
> > 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. :)
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.
>> > 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. :)
On Thu, Jan 27, 2011 at 21:56, C Snover <goo...@zetafleet.com> wrote: > Hi everyone,
> I’ve posted my article at http://zetafleet.com/blog/google-chromes-heap-profiler-and-memory-tim.... > 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. :)
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....
> > 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. :)
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 :)
On Sunday, February 27, 2011 1:07:49 PM UTC-5, Davit Barbakadze wrote:
> 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.... > > > 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. :)