devtools-docs/docs/memory-analysis-101.html

141 строка
6.1 KiB
HTML

{{+bindTo:partials.standard_devtools_article}}
<h1>Memory Analysis 101</h1>
<p>This is an introduction to memory analysis. Terms and notions
described here are used in the Heap Profiler UI and the corresponding
documentation. You need to be familiar with them to use the tool
effectively.</p>
<div class="collapsible">
<h2 id="common_terms">Common Terms</h2>
<p>This section describes common terms used in memory analysis,
and is applicable to a variety of memory profiling tools for different
languages. If you already have experience with, say, Java or .Net
memory profilers, chances are high that you are familiar with
them.</p>
<h3 id="object_sizes">Object Sizes</h3>
<p>Memory can be held by an object in two ways: directly by the object
itself, and implicitly by holding references to other objects, and
thus preventing them from being automatically disposed by a garbage
collector (<em>GC</em> for short).</p>
<p>The size of memory that is held by the object itself is
called <em>shallow size</em>. Typical JavaScript objects have some
memory reserved for their description and for storing immediate
values.</p>
<p>Usually, only arrays and strings can have significant shallow
sizes. However, strings often have their main storage in renderer
memory, exposing only a small wrapper object on the JavaScript heap.</p>
<p>Nevertheless, even a small object can hold a large amount of memory
indirectly, by preventing other objects from being disposed by the
automatic garbage collection process. The size of memory that will be
freed, when the object itself is deleted, and its dependent objects
made unreachable from GC roots, is called <em>retained size</em>.</p>
<h3 id="retaining_paths">Retaining Paths</h3>
<p>The heap is a network of interconnected objects. In the mathematical
world, this structure is called a graph. A graph is constructed
from <em>nodes</em> connected by means of <em>edges</em>. Both nodes
and edges have labels: nodes (objects) are labelled using the name of
the constructor function that was used to build them, edges are
labelled using the names of properties.</p>
<p>The sequence of edges that needs to be traversed in order to reach
one object from another, is called a <em>path</em>. Usually, we are
only interested in <em>simple</em> paths, i.e. paths that do not go
through the same node twice.</p>
<p>We call a <em>retaining path</em> any path from GC roots to a
particular object. If there are no such paths, the object is called
<em>unreachable</em> and is subject to disposal during garbage
collection.</p>
<h3 id="dominators">Dominators</h3>
<p>The dominator of an object <strong>A</strong> is an object that
exists in every simple path from the root to the
object <strong>A</strong>. That means, having the dominator object
removed from the heap (with all its references being cut), the
object <strong>A</strong> will become unreachable from GC roots, and will be
disposed.</p>
<p>Dominator objects comprise a tree structure, because each object
has exactly one dominator. A dominator of an object may lack direct
references to an object it dominates, that is, the dominators tree is
not a spanning tree of the graph.</p>
<p>Collection-like objects may retain big amounts of memory, when
they dominate other objects. Such nodes of the tree are called
<em>accumulation points</em>.</p>
</div>
<div class="collapsible">
<h2 id="v8_specifics">V8 Specifics</h2>
<p>In this section we describe some memory-related topics that
only correspond to the V8 JavaScript virtual machine. Reading them might
help to understand why heap snapshots look this way.</p>
<h3 id="primitive_objects">JavaScript Object Representation</h3>
<p>Numbers can be presented either as immediate 31-bit integer values
(they are called <em>small integers</em>, or <em>SMIs</em> for short),
or as heap objects (called <em>heap numbers</em>). The latter are used
for values that can't fit into the SMI form, e.g. doubles, or for
cases when a value needs to be <em>boxed</em>, e.g. for setting
properties on it.</p>
<p>String content can be either stored in the VM heap, or externally
in the renderer's memory. Content received from the Web (e.g. scripts
sources) doesn't get copied onto the VM heap, instead, a wrapper object is
created and used to access external storage.</p>
<p>When two strings are concatenated, their contents are initially
stored separately, and are joined only logically, using an object
called <em>cons string</em>. Joining of the cons string contents is
performed only when it's needed, e.g. when a substring of a joined
string needs to be constructed.</p>
<p>Arrays are used extensively in the V8 VM for storing large amounts of
data. Dictionaries (sets of key-value pairs) are backed up by arrays.
Thus, arrays are the basic building block for JavaScript objects. A
typical JavaScript object posesses two arrays: one for storing named
properties, another for storing numeric elements. In the case when the
number of properties is very small, they can be stored internally in
the JavaScript object itself.</p>
<p>A <em>map</em> object describes object kind and its layout. For example,
maps are used to describe implicit object hierarchies, as described
<a href="https://developers.google.com/v8/design#prop_access">here</a>.</p>
<h3 id="object_groups">Object Groups</h3>
<p>Each native <em>objects group</em> is made up from objects that hold
mutual references to each other. Consider for example a DOM subtree,
where every node has a link to its parent and links to the next child and
next sibling, thus forming a connected graph. Note that native objects
are not represented in the JavaScript heap &mdash; that's why they
have zero size. Instead, <em>wrapper objects</em> are created. Each
wrapper object holds a reference to the corresponding native object,
for redirecting commands to it. In its own turn, an object group holds
wrapper objects. However, this doesn't create an uncollectable cycle,
as GC is smart enough to release object groups whose wrappers are no
longer referenced. But forgetting to release a single wrapper will
hold the whole group and associated wrappers.</p>
</div>
{{/partials.standard_devtools_article}}