summaryrefslogtreecommitdiffstats
path: root/devtools/docs/user/memory
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:47:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:47:29 +0000
commit0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch)
treea31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /devtools/docs/user/memory
parentInitial commit. (diff)
downloadfirefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.tar.xz
firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.zip
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'devtools/docs/user/memory')
-rw-r--r--devtools/docs/user/memory/aggregate_view/index.rst183
-rw-r--r--devtools/docs/user/memory/aggregate_view/memory-tool-aggregate-view.pngbin0 -> 55175 bytes
-rw-r--r--devtools/docs/user/memory/aggregate_view/memory-tool-call-stack-expanded.pngbin0 -> 69021 bytes
-rw-r--r--devtools/docs/user/memory/aggregate_view/memory-tool-call-stack.pngbin0 -> 37960 bytes
-rw-r--r--devtools/docs/user/memory/aggregate_view/memory-tool-in-group-icon.pngbin0 -> 6376 bytes
-rw-r--r--devtools/docs/user/memory/aggregate_view/memory-tool-in-group-retaining-paths.pngbin0 -> 47488 bytes
-rw-r--r--devtools/docs/user/memory/aggregate_view/memory-tool-in-group.pngbin0 -> 32277 bytes
-rw-r--r--devtools/docs/user/memory/aggregate_view/memory-tool-inverted-call-stack.pngbin0 -> 42582 bytes
-rw-r--r--devtools/docs/user/memory/aggregate_view/memory-tool-switch-view.pngbin0 -> 26038 bytes
-rw-r--r--devtools/docs/user/memory/basic_operations/index.rst95
-rw-r--r--devtools/docs/user/memory/basic_operations/memory-1-small.pngbin0 -> 12408 bytes
-rw-r--r--devtools/docs/user/memory/basic_operations/memory-2-small.pngbin0 -> 20870 bytes
-rw-r--r--devtools/docs/user/memory/basic_operations/memory-3-small.pngbin0 -> 20962 bytes
-rw-r--r--devtools/docs/user/memory/basic_operations/memory-4-small.pngbin0 -> 20940 bytes
-rw-r--r--devtools/docs/user/memory/basic_operations/memory-5-small.pngbin0 -> 21140 bytes
-rw-r--r--devtools/docs/user/memory/basic_operations/memory-6-small.pngbin0 -> 20922 bytes
-rw-r--r--devtools/docs/user/memory/basic_operations/memory-7-small.pngbin0 -> 20555 bytes
-rw-r--r--devtools/docs/user/memory/dom_allocation_example/index.rst57
-rw-r--r--devtools/docs/user/memory/dominators/index.rst85
-rw-r--r--devtools/docs/user/memory/dominators/memory-graph-dominator-multiple-references.svg4
-rw-r--r--devtools/docs/user/memory/dominators/memory-graph-dominators.svg4
-rw-r--r--devtools/docs/user/memory/dominators/memory-graph-immediate-dominator.svg4
-rw-r--r--devtools/docs/user/memory/dominators/memory-graph-unreachable.svg4
-rw-r--r--devtools/docs/user/memory/dominators/memory-graph.svg4
-rw-r--r--devtools/docs/user/memory/dominators_view/dominators-1.pngbin0 -> 28248 bytes
-rw-r--r--devtools/docs/user/memory/dominators_view/dominators-10.pngbin0 -> 22011 bytes
-rw-r--r--devtools/docs/user/memory/dominators_view/dominators-2.pngbin0 -> 29454 bytes
-rw-r--r--devtools/docs/user/memory/dominators_view/dominators-3.pngbin0 -> 33064 bytes
-rw-r--r--devtools/docs/user/memory/dominators_view/dominators-4.pngbin0 -> 40001 bytes
-rw-r--r--devtools/docs/user/memory/dominators_view/dominators-5.pngbin0 -> 31844 bytes
-rw-r--r--devtools/docs/user/memory/dominators_view/dominators-6.pngbin0 -> 56667 bytes
-rw-r--r--devtools/docs/user/memory/dominators_view/dominators-7.pngbin0 -> 26682 bytes
-rw-r--r--devtools/docs/user/memory/dominators_view/dominators-8.pngbin0 -> 26678 bytes
-rw-r--r--devtools/docs/user/memory/dominators_view/dominators-9.pngbin0 -> 45509 bytes
-rw-r--r--devtools/docs/user/memory/dominators_view/index.rst174
-rw-r--r--devtools/docs/user/memory/index.rst52
-rw-r--r--devtools/docs/user/memory/monster_example/index.rst80
-rw-r--r--devtools/docs/user/memory/monster_example/monsters.svg4
-rw-r--r--devtools/docs/user/memory/tree_map_view/index.rst47
-rw-r--r--devtools/docs/user/memory/tree_map_view/treemap-bbc.pngbin0 -> 48965 bytes
-rw-r--r--devtools/docs/user/memory/tree_map_view/treemap-domnodes.pngbin0 -> 10998 bytes
-rw-r--r--devtools/docs/user/memory/tree_map_view/treemap-monsters.pngbin0 -> 20713 bytes
42 files changed, 797 insertions, 0 deletions
diff --git a/devtools/docs/user/memory/aggregate_view/index.rst b/devtools/docs/user/memory/aggregate_view/index.rst
new file mode 100644
index 0000000000..94118e8c5b
--- /dev/null
+++ b/devtools/docs/user/memory/aggregate_view/index.rst
@@ -0,0 +1,183 @@
+==============
+Aggregate view
+==============
+
+Before Firefox 48, this was the default view of a heap snapshot. After Firefox 48, the default view is the :doc:`Tree map view <../tree_map_view/index>`, and you can switch to the Aggregate view using the dropdown labeled "View:":
+
+.. image:: memory-tool-switch-view.png
+ :class: center
+
+
+The Aggregate view looks something like this:
+
+.. image:: memory-tool-aggregate-view.png
+ :class: center
+
+
+It presents a breakdown of the heap's contents, as a table. There are three main ways to group the data:
+
+
+- :ref:`Type <memory-aggregate-view-type>`
+- :ref:`Call Stack <memory-aggregate-view-call-stack>`
+- :ref:`Inverted Call Stack <memory-aggregate-view-inverted-call-stack>`
+
+You can switch between them using the dropdown menu labeled "Group by:" located at the top of the panel:
+
+There's also a box labeled "Filter" at the top-right of the pane. You can use this to filter the contents of the snapshot that are displayed, so you can quickly see, for example, how many objects of a specific class were allocated.
+
+
+.. _memory-aggregate-view-type:
+
+Type
+****
+
+This is the default view, which looks something like this:
+
+.. image:: memory-tool-aggregate-view.png
+ :class: center
+
+It groups the things on the heap into types, including:
+
+
+- **JavaScript objects:** such as `Function <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function>`_ or `Array <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array>`_
+- **DOM elements:** such as `HTMLSpanElement <https://developer.mozilla.org/en-US/docs/Web/API/HTMLSpanElement>`_ or `Window <https://developer.mozilla.org/en-US/docs/Web/API/Window>`_
+- **Strings:** listed as ``"strings"``
+- **JavaScript sources:** listed as "``JSScript"``
+- **Internal objects:** such as "``js::Shape``". These are prefixed with ``"js::"``.
+
+
+Each type gets a row in the table, and rows are ordered by the amount of memory occupied by objects of that type. For example, in the screenshot above you can see that JavaScript ``Object`` account for most memory, followed by strings.
+
+
+- The "Total Count" column shows you the number of objects of each category that are currently allocated.
+- The "Total Bytes" column shows you the number of bytes occupied by objects in each category, and that number as a percentage of the whole heap size for that tab.
+
+
+The screenshots in this section are taken from a snapshot of the :doc:`monster example page <../monster_example/index>`.
+
+
+For example, in the screenshot above, you can see that:
+
+- there are four ``Array`` objects
+- that account for 15% of the total heap.
+
+
+Next to the type's name, there's an icon that contains three stars arranged in a triangle:
+
+.. image:: memory-tool-in-group-icon.png
+ :class: center
+
+
+Click this to see every instance of that type. For example, the entry for ``Array`` tells us that there are four ``Array`` objects in the snapshot. If we click the star-triangle, we'll see all four ``Array`` instances:
+
+.. image:: memory-tool-in-group.png
+ :class: center
+
+
+For each instance, you can see the :ref:`retained size and shallow size <shallow-and-retained-size>` of that instance. In this case, you can see that the first three arrays have a fairly large shallow size (5% of the total heap usage) and a much larger retained size (26% of the total).
+
+On the right-hand side is a pane that just says "Select an item to view its retaining paths". If you select an item, you'll see the :ref:`Retaining paths panel <memory-dominators-view-retaining-paths-panel>` for that item:
+
+.. image:: memory-tool-in-group-retaining-paths.png
+ :class: center
+
+
+.. _memory-aggregate-view-call-stack:
+
+Call Stack
+**********
+
+The Call Stack shows you exactly where in your code you are making heap allocations.
+
+Because tracing allocations has a runtime cost, it must be explicitly enabled by checking "Record call stacks" *before* you allocate the memory in the snapshot.
+
+You'll then see a list of all the functions that allocated objects, ordered by the size of the allocations they made:
+
+.. image:: memory-tool-call-stack.png
+ :class: center
+
+
+The structure of this view is very much like the structure of the :doc:`Call Tree <../../performance/call_tree/index>`, only it shows allocations rather than processor samples. So, for example, the first entry says that:
+
+
+- 4,832,592 bytes, comprising 93% of the total heap usage, were allocated in a function at line 35 of "alloc.js", **or in functions called by that function**
+
+
+We can use the disclosure triangle to drill down the call tree, to find the exact place your code made those allocations.
+
+It's easier to explain this with reference to a simple example. For :doc:`DOM allocation example <../dom_allocation_example/index>`. This page runs a script that creates a large number of DOM nodes (200 `HTMLDivElement <https://developer.mozilla.org/en-US/docs/Web/API/HTMLDivElement>`_ objects and 4000 `HTMLSpanElement <https://developer.mozilla.org/en-US/docs/Web/API/HTMLSpanElement>`_ objects).
+
+Let's get an allocation trace:
+
+
+1. open the Memory tool
+2. check "Record call stacks"
+3. load https://firefox-devtools.github.io/performance-scenarios/dom-allocs/alloc.html
+4. take a snapshot
+5. select "View/Aggregate"
+6. select "Group by/Call Stack"
+
+.. raw:: html
+
+ <iframe width="560" height="315" src="https://www.youtube.com/embed/DyLulu9eoKY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
+ <br/>
+ <br/>
+
+You should see something like this:
+
+.. image:: memory-tool-call-stack.png
+ :class: center
+
+
+This is telling us that 93% of the total heap snapshot was allocated in functions called from "alloc.js", line 35 (our initial ``createToolbars()`` call).
+
+We can use the disclosure arrow to expand the tree to find out exactly where we're allocating memory:
+
+.. image:: memory-tool-call-stack-expanded.png
+ :class: center
+
+
+This is where the "Bytes" and "Count" columns are useful: they show allocation size and number of allocations at that exact point.
+
+So in the example above, we can see that we made 4002 allocations, accounting for 89% of the total heap, in ``createToolbarButton()``, at `alloc.js line 9, position 23 <https://github.com/mdn/performance-scenarios/blob/gh-pages/dom-allocs/scripts/alloc.js#L9>`_: that is, the exact point where we create the `<span> <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span>`_ elements.
+
+The file name and line number is a link: if we click it, we go directly to that line in the debugger:
+
+.. raw:: html
+
+ <iframe width="560" height="315" src="https://www.youtube.com/embed/zlnJcr1IFyY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
+ <br/>
+ <br/>
+
+
+.. _memory-aggregate-view-inverted-call-stack:
+
+Inverted Call Stack
+*******************
+
+The Call Stack view is top-down: it shows allocations that happen at that point **or points deeper in the call tree**. So it's good for getting an overview of where your program is memory-hungry. However, this view means you have to drill a long way down to find the exact place where the allocations are happening.
+
+The "Inverted Call Stack" view helps with that. It gives you the bottom-up view of the program showing the exact places where allocations are happening, ranked by the size of allocation at each place. The disclosure arrow then walks you back up the call tree towards the top level.
+
+Let's see what the example looks like when we select "Inverted Call Stack":
+
+.. image:: memory-tool-inverted-call-stack.png
+ :class: center
+
+
+Now at the top we can immediately see the ``createToolbarButton()`` call accounting for 89% of the heap usage in our page.
+
+
+(no stack available)
+********************
+
+In the example above you'll note that 7% of the heap is marked "(no stack available)". This is because not all heap usage results from your JavaScript.
+
+For example:
+
+
+- any scripts the page loads occupy heap space
+- sometimes an object is allocated when there is no JavaScript on the stack. For example, DOM `Event <https://developer.mozilla.org/en-US/docs/Web/API/Event>`_ objects are allocated before the JavaScript is run and event handlers are called.
+
+
+Many real-world pages will have a much higher "(no stack available)" share than 7%.
diff --git a/devtools/docs/user/memory/aggregate_view/memory-tool-aggregate-view.png b/devtools/docs/user/memory/aggregate_view/memory-tool-aggregate-view.png
new file mode 100644
index 0000000000..653710979f
--- /dev/null
+++ b/devtools/docs/user/memory/aggregate_view/memory-tool-aggregate-view.png
Binary files differ
diff --git a/devtools/docs/user/memory/aggregate_view/memory-tool-call-stack-expanded.png b/devtools/docs/user/memory/aggregate_view/memory-tool-call-stack-expanded.png
new file mode 100644
index 0000000000..fe2364da58
--- /dev/null
+++ b/devtools/docs/user/memory/aggregate_view/memory-tool-call-stack-expanded.png
Binary files differ
diff --git a/devtools/docs/user/memory/aggregate_view/memory-tool-call-stack.png b/devtools/docs/user/memory/aggregate_view/memory-tool-call-stack.png
new file mode 100644
index 0000000000..52a96015da
--- /dev/null
+++ b/devtools/docs/user/memory/aggregate_view/memory-tool-call-stack.png
Binary files differ
diff --git a/devtools/docs/user/memory/aggregate_view/memory-tool-in-group-icon.png b/devtools/docs/user/memory/aggregate_view/memory-tool-in-group-icon.png
new file mode 100644
index 0000000000..6354a3d377
--- /dev/null
+++ b/devtools/docs/user/memory/aggregate_view/memory-tool-in-group-icon.png
Binary files differ
diff --git a/devtools/docs/user/memory/aggregate_view/memory-tool-in-group-retaining-paths.png b/devtools/docs/user/memory/aggregate_view/memory-tool-in-group-retaining-paths.png
new file mode 100644
index 0000000000..191115f041
--- /dev/null
+++ b/devtools/docs/user/memory/aggregate_view/memory-tool-in-group-retaining-paths.png
Binary files differ
diff --git a/devtools/docs/user/memory/aggregate_view/memory-tool-in-group.png b/devtools/docs/user/memory/aggregate_view/memory-tool-in-group.png
new file mode 100644
index 0000000000..88aac55e9e
--- /dev/null
+++ b/devtools/docs/user/memory/aggregate_view/memory-tool-in-group.png
Binary files differ
diff --git a/devtools/docs/user/memory/aggregate_view/memory-tool-inverted-call-stack.png b/devtools/docs/user/memory/aggregate_view/memory-tool-inverted-call-stack.png
new file mode 100644
index 0000000000..5a951c2e8c
--- /dev/null
+++ b/devtools/docs/user/memory/aggregate_view/memory-tool-inverted-call-stack.png
Binary files differ
diff --git a/devtools/docs/user/memory/aggregate_view/memory-tool-switch-view.png b/devtools/docs/user/memory/aggregate_view/memory-tool-switch-view.png
new file mode 100644
index 0000000000..bb3cb0cdb3
--- /dev/null
+++ b/devtools/docs/user/memory/aggregate_view/memory-tool-switch-view.png
Binary files differ
diff --git a/devtools/docs/user/memory/basic_operations/index.rst b/devtools/docs/user/memory/basic_operations/index.rst
new file mode 100644
index 0000000000..c8149ef344
--- /dev/null
+++ b/devtools/docs/user/memory/basic_operations/index.rst
@@ -0,0 +1,95 @@
+================
+Basic operations
+================
+
+
+.. _memory-basic-operations-opening-the-memory-tool:
+
+Opening the Memory tool
+***********************
+
+Before Firefox 50, the Memory tool is not enabled by default. To enable it, open the developer tool settings, and check the "Memory" box under "Default Firefox Developer Tools".
+
+From Firefox 50 onwards, the Memory tool is enabled by default.
+
+
+.. _memory-basic-operations-taking-a-heap-snapshot:
+
+Taking a heap snapshot
+**********************
+
+To take a snapshot of the heap, click the "Take snapshot" button, or the camera icon on the left:
+
+.. image:: memory-1-small.png
+ :class: center
+
+The snapshot will occupy the large pane on the right-hand side. On the left, you'll see an entry for the new snapshot, including its timestamp, size, and controls to save or clear this snapshot:
+
+.. image:: memory-2-small.png
+ :class: center
+
+
+.. _memory-basic-operations-clearing-a-snapshot:
+
+Clearing a snapshot
+*******************
+
+To remove a snapshot, click the "X" icon:
+
+.. image:: memory-3-small.png
+ :class: center
+
+
+.. _memory-basic-operations-saving-and-loading-snapshots:
+
+Saving and loading snapshots
+****************************
+
+If you close the Memory tool, all unsaved snapshots will be discarded. To save a snapshot click "Save":
+
+.. image:: memory-4-small.png
+ :class: center
+
+You'll be prompted for a name and location, and the file will be saved with an ``.fxsnapshot`` extension.
+
+To load a snapshot from an existing ``.fxsnapshot`` file, click the import button, which looks like a rectangle with an arrow rising from it (before Firefox 49, this button was labeled with the text "Import..."):
+
+.. image:: memory-5-small.png
+ :class: center
+
+You'll be prompted to find a snapshot file on disk.
+
+
+.. _memory-basic-operations-comparing-snapshots:
+
+Comparing snapshots
+*******************
+
+Starting in Firefox 45, you can diff two heap snapshots. The diff shows you where memory was allocated or freed between the two snapshots.
+
+To create a diff, click the button that looks like a Venn diagram next to the camera icon (before Firefox 47, this looked like a "+/-" icon):
+
+.. image:: memory-6-small.png
+ :class: center
+
+You'll be prompted to select the snapshot to use as a baseline, then the snapshot to compare. The tool then shows you the differences between the two snapshots:
+
+.. raw:: html
+
+ <iframe width="560" height="315" src="https://www.youtube.com/embed/3Ow-mdK6b2M" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
+ <br/>
+ <br/>
+
+.. note::
+ When you're looking at a comparison, you can't use the Dominators view or the Tree Map view.
+
+
+.. _memory-basic-operations-recording-call-stacks:
+
+Recording call stacks
+*********************
+
+The Memory tool can tell you exactly where in your code you are allocating memory. However, recording this information has a run-time cost, so you must ask the tool to record memory calls *before* the memory is allocated, if you want to see memory call sites in the snapshot. To do this, check "Record call stacks" (before Firefox 49 this was labeled "Record allocation stacks"):
+
+.. image:: memory-7-small.png
+ :class: center
diff --git a/devtools/docs/user/memory/basic_operations/memory-1-small.png b/devtools/docs/user/memory/basic_operations/memory-1-small.png
new file mode 100644
index 0000000000..a2076330b8
--- /dev/null
+++ b/devtools/docs/user/memory/basic_operations/memory-1-small.png
Binary files differ
diff --git a/devtools/docs/user/memory/basic_operations/memory-2-small.png b/devtools/docs/user/memory/basic_operations/memory-2-small.png
new file mode 100644
index 0000000000..569b0d9d66
--- /dev/null
+++ b/devtools/docs/user/memory/basic_operations/memory-2-small.png
Binary files differ
diff --git a/devtools/docs/user/memory/basic_operations/memory-3-small.png b/devtools/docs/user/memory/basic_operations/memory-3-small.png
new file mode 100644
index 0000000000..5d77bd7f60
--- /dev/null
+++ b/devtools/docs/user/memory/basic_operations/memory-3-small.png
Binary files differ
diff --git a/devtools/docs/user/memory/basic_operations/memory-4-small.png b/devtools/docs/user/memory/basic_operations/memory-4-small.png
new file mode 100644
index 0000000000..9a1e18da6f
--- /dev/null
+++ b/devtools/docs/user/memory/basic_operations/memory-4-small.png
Binary files differ
diff --git a/devtools/docs/user/memory/basic_operations/memory-5-small.png b/devtools/docs/user/memory/basic_operations/memory-5-small.png
new file mode 100644
index 0000000000..e3277186dc
--- /dev/null
+++ b/devtools/docs/user/memory/basic_operations/memory-5-small.png
Binary files differ
diff --git a/devtools/docs/user/memory/basic_operations/memory-6-small.png b/devtools/docs/user/memory/basic_operations/memory-6-small.png
new file mode 100644
index 0000000000..da69b93e51
--- /dev/null
+++ b/devtools/docs/user/memory/basic_operations/memory-6-small.png
Binary files differ
diff --git a/devtools/docs/user/memory/basic_operations/memory-7-small.png b/devtools/docs/user/memory/basic_operations/memory-7-small.png
new file mode 100644
index 0000000000..844565a8b4
--- /dev/null
+++ b/devtools/docs/user/memory/basic_operations/memory-7-small.png
Binary files differ
diff --git a/devtools/docs/user/memory/dom_allocation_example/index.rst b/devtools/docs/user/memory/dom_allocation_example/index.rst
new file mode 100644
index 0000000000..85a9ab9036
--- /dev/null
+++ b/devtools/docs/user/memory/dom_allocation_example/index.rst
@@ -0,0 +1,57 @@
+======================
+DOM allocation example
+======================
+
+This article describes a very simple web page that we'll use to illustrate some features of the Memory tool.
+
+You can try out the site at https://firefox-devtools.github.io/performance-scenarios/dom-allocs/alloc.html.
+
+It just contains a script that creates a large number of DOM nodes:
+
+.. code-block:: javascript
+
+ var toolbarButtonCount = 20;
+ var toolbarCount = 200;
+
+ function getRandomInt(min, max) {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+ }
+
+ function createToolbarButton() {
+ var toolbarButton = document.createElement("span");
+ toolbarButton.classList.add("toolbarbutton");
+ // stop Spidermonkey from sharing instances
+ toolbarButton[getRandomInt(0,5000)] = "foo";
+ return toolbarButton;
+ }
+
+ function createToolbar() {
+ var toolbar = document.createElement("div");
+ // stop Spidermonkey from sharing instances
+ toolbar[getRandomInt(0,5000)] = "foo";
+ for (var i = 0; i < toolbarButtonCount; i++) {
+ var toolbarButton = createToolbarButton();
+ toolbar.appendChild(toolbarButton);
+ }
+ return toolbar;
+ }
+
+ function createToolbars() {
+ var container = document.getElementById("container");
+ for (var i = 0; i < toolbarCount; i++) {
+ var toolbar = createToolbar();
+ container.appendChild(toolbar);
+ }
+ }
+
+ createToolbars();
+
+A simple pseudocode representation of how this code operates looks like this:
+
+.. code-block:: JavaScript
+
+ createToolbars()
+ -> createToolbar() // called 200 times, creates 1 DIV element each time
+ -> createToolbarButton() // called 20 times per toolbar, creates 1 SPAN element each time</pre>
+
+In total, then, it creates 200 `HTMLDivElement <https://developer.mozilla.org/en-US/docs/Web/API/HTMLDivElement>`_ objects, and 4000 `HTMLSpanElement <https://developer.mozilla.org/en-US/docs/Web/API/HTMLSpanElement>`_ objects.
diff --git a/devtools/docs/user/memory/dominators/index.rst b/devtools/docs/user/memory/dominators/index.rst
new file mode 100644
index 0000000000..443b4c6e7b
--- /dev/null
+++ b/devtools/docs/user/memory/dominators/index.rst
@@ -0,0 +1,85 @@
+==========
+Dominators
+==========
+
+This article provides an introduction to the concepts of *Reachability*, *Shallow* versus *Retained* size, and *Dominators*, as they apply in garbage-collected languages like JavaScript.
+
+These concepts matter in memory analysis, because often an object may itself be small, but may hold references to other much larger objects, and by doing this will prevent the garbage collector from freeing that extra memory.
+
+You can see the dominators in a page using the :doc:`Dominators view <../dominators_view/index>` in the Memory tool.
+
+
+With a garbage-collected language, like JavaScript, the programmer doesn't generally have to worry about deallocating memory. They can just create and use objects, and when the objects are no longer needed, the runtime takes care of cleaning up, and frees the memory the objects occupied.
+
+
+.. _memory-dominators-reachability:
+
+Reachability
+************
+
+In modern JavaScript implementations, the runtime decides whether an object is no longer needed based on *reachability*. In this system the heap is represented as one or more graphs. Each node in the graph represents an object, and each connection between nodes (edge) represents a reference from one object to another. The graph starts at a root node, indicated in these diagrams with "R".
+
+.. image:: memory-graph.svg
+ :class: center
+
+
+During garbage collection, the runtime traverses the graph, starting at the root, and marks every object it finds. Any objects it doesn't find are unreachable, and can be deallocated.
+
+So when an object becomes unreachable (for example, because it is only referenced by a single local variable which goes out of scope) then any objects it references also become unreachable, as long as no other objects reference them:
+
+.. image:: memory-graph-unreachable.svg
+ :class: center
+
+
+Conversely, this means that objects are kept alive as long as some other reachable object is holding a reference to them.
+
+
+.. _shallow-and-retained-size:
+
+Shallow and retained size
+*************************
+
+This gives rise to a distinction between two ways to look at the size of an object:
+
+
+- *shallow size*: the size of the object itself
+- *retained size*: the size of the object itself, plus the size of other objects that are kept alive by this object
+
+
+Often, objects will have a small shallow size but a much larger retained size, through the references they contain to other objects. Retained size is an important concept in analyzing memory usage, because it answers the question "if this object ceases to exist, what's the total amount of memory freed?".
+
+
+Dominators
+**********
+
+A related concept is that of the *dominator*. Node B is said to dominate node A if every path from the root to A passes through B:
+
+.. image:: memory-graph-dominators.svg
+ :class: center
+
+
+If any of node A's dominators are freed, then node A itself becomes eligible for garbage collection.
+
+
+.. _memory-dominators-immediate-dominator:
+
+If node B dominates node A, but does not dominate any of A's other dominators, then B is the *immediate dominator* of A:
+
+.. image:: memory-graph-immediate-dominator.svg
+ :class: center
+
+
+.. _memory-dominators-multiple-paths:
+
+One slight subtlety here is that if an object A is referenced by two other unrelated objects B and C, then neither object is its dominator, because you could remove either B or C from the graph, and A would still be retained by its other referrer. Instead, the immediate dominator of A would be its first common ancestor:
+
+.. image:: memory-graph-dominator-multiple-references.svg
+ :class: center
+
+
+See also
+********
+
+
+- `Dominators in graph theory <https://en.wikipedia.org/wiki/Dominator_%28graph_theory%29>`_.
+- `Tracing garbage collection <https://en.wikipedia.org/wiki/Tracing_garbage_collection>`_.
diff --git a/devtools/docs/user/memory/dominators/memory-graph-dominator-multiple-references.svg b/devtools/docs/user/memory/dominators/memory-graph-dominator-multiple-references.svg
new file mode 100644
index 0000000000..4ac6b45812
--- /dev/null
+++ b/devtools/docs/user/memory/dominators/memory-graph-dominator-multiple-references.svg
@@ -0,0 +1,4 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" viewBox="114 20 158 212" width="158pt" height="212pt"><defs><linearGradient x1="0" x2="1" id="a" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#e5f2f2"/><stop offset="1" stop-color="#cff2f2"/></linearGradient><linearGradient id="b" xl:href="#a" gradientTransform="matrix(0 38 -38 0 183 90.5)"/><linearGradient id="c" xl:href="#a" gradientTransform="matrix(0 38 -38 0 135 141.5)"/><linearGradient id="d" xl:href="#a" gradientTransform="rotate(90 44.5 186) scale(38)"/><linearGradient id="f" xl:href="#a" gradientTransform="matrix(0 38 -38 0 183 191.5)"/><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="e" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#000"><path d="M8 0L0-3v6z" fill="currentColor" stroke="currentColor"/></marker><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="g" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#000"><path d="M8 0H0m0-3l8 3-8 3" fill="none" stroke="currentColor"/></marker></defs><g fill="none"><circle cx="183" cy="109.5" r="19" fill="url(#b)"/><circle cx="183" cy="109.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="135" cy="160.5" r="19" fill="url(#c)"/><circle cx="135" cy="160.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="230.5" cy="160.5" r="19" fill="url(#d)"/><circle cx="230.5" cy="160.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M169.978 123.336l-15.171 16.119m41.143-16.051l14.853 15.948"/><circle cx="183" cy="210.5" r="19" fill="url(#f)"/><circle cx="183" cy="210.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><text transform="translate(172.8 201.5)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="5.016" y="15" textLength="10.368">A</tspan></text><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M148.158 174.206l14.828 15.446"/><text transform="translate(169 26.5)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x=".096" y="15" textLength="10.368">A</tspan><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="9.28" y="15" textLength="4.448">’</tspan><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="12.544" y="15" textLength="85.36">s dominator</tspan></text><path marker-end="url(#g)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="4,4" d="M210.905 50.5l-15.546 32.87"/><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M217.414 174.275l-14.509 15.272"/></g></svg> \ No newline at end of file
diff --git a/devtools/docs/user/memory/dominators/memory-graph-dominators.svg b/devtools/docs/user/memory/dominators/memory-graph-dominators.svg
new file mode 100644
index 0000000000..e3a63c96df
--- /dev/null
+++ b/devtools/docs/user/memory/dominators/memory-graph-dominators.svg
@@ -0,0 +1,4 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" viewBox="60 57 353 232" width="353pt" height="232pt"><defs><linearGradient x1="0" x2="1" id="a" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#e5f2f2"/><stop offset="1" stop-color="#cff2f2"/></linearGradient><linearGradient id="b" xl:href="#a" gradientTransform="matrix(0 38 -38 0 183 90.5)"/><linearGradient id="c" xl:href="#a" gradientTransform="matrix(0 38 -38 0 135 141.5)"/><linearGradient id="d" xl:href="#a" gradientTransform="rotate(90 44.5 186) scale(38)"/><linearGradient id="f" xl:href="#a" gradientTransform="matrix(0 38 -38 0 81.5 196.5)"/><linearGradient id="g" xl:href="#a" gradientTransform="rotate(90 41 238.5) scale(38)"/><linearGradient id="h" xl:href="#a" gradientTransform="rotate(90 -8.5 240) scale(38)"/><linearGradient id="i" xl:href="#a" gradientTransform="matrix(0 38 -38 0 327 248.5)"/><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="e" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#000"><path d="M8 0L0-3v6z" fill="currentColor" stroke="currentColor"/></marker><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="j" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#000"><path d="M8 0H0m0-3l8 3-8 3" fill="none" stroke="currentColor"/></marker></defs><g fill="none"><circle cx="183" cy="109.5" r="19" fill="url(#b)"/><circle cx="183" cy="109.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><text transform="translate(172.8 100.5)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="4.72" y="15" textLength="10.96">R</tspan></text><circle cx="135" cy="160.5" r="19" fill="url(#c)"/><circle cx="135" cy="160.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="230.5" cy="160.5" r="19" fill="url(#d)"/><circle cx="230.5" cy="160.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M169.978 123.336l-15.171 16.119m41.143-16.051l14.853 15.948"/><circle cx="81.5" cy="215.5" r="19" fill="url(#f)"/><circle cx="81.5" cy="215.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M121.752 174.119l-20.101 20.665"/><circle cx="279.5" cy="216.5" r="19" fill="url(#g)"/><circle cx="279.5" cy="216.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="231.5" cy="267.5" r="19" fill="url(#h)"/><circle cx="231.5" cy="267.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="327" cy="267.5" r="19" fill="url(#i)"/><circle cx="327" cy="267.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><text transform="translate(316.8 258.5)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="5.016" y="15" textLength="10.368">A</tspan></text><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M243.012 174.799l17.457 19.951m31.981 35.654l14.853 15.948m-40.825-16.016l-15.171 16.119"/><text transform="translate(301.5 63)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x=".096" y="15" textLength="10.368">A</tspan><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="9.28" y="15" textLength="4.448">’</tspan><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="12.544" y="15" textLength="93.36">s dominators</tspan></text><path marker-end="url(#j)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="4,4" d="M296.5 84.682l-85.265 18.644M333.483 87l-79.457 56.709M346.715 87l-53.899 103.845"/></g></svg> \ No newline at end of file
diff --git a/devtools/docs/user/memory/dominators/memory-graph-immediate-dominator.svg b/devtools/docs/user/memory/dominators/memory-graph-immediate-dominator.svg
new file mode 100644
index 0000000000..8288524884
--- /dev/null
+++ b/devtools/docs/user/memory/dominators/memory-graph-immediate-dominator.svg
@@ -0,0 +1,4 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" viewBox="60 57 350 232" width="350pt" height="232pt"><defs><linearGradient x1="0" x2="1" id="a" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#e5f2f2"/><stop offset="1" stop-color="#cff2f2"/></linearGradient><linearGradient id="b" xl:href="#a" gradientTransform="matrix(0 38 -38 0 183 90.5)"/><linearGradient id="c" xl:href="#a" gradientTransform="matrix(0 38 -38 0 135 141.5)"/><linearGradient id="d" xl:href="#a" gradientTransform="rotate(90 44.5 186) scale(38)"/><linearGradient id="f" xl:href="#a" gradientTransform="matrix(0 38 -38 0 81.5 196.5)"/><linearGradient id="g" xl:href="#a" gradientTransform="rotate(90 41 238.5) scale(38)"/><linearGradient id="h" xl:href="#a" gradientTransform="rotate(90 -8.5 240) scale(38)"/><linearGradient id="i" xl:href="#a" gradientTransform="matrix(0 38 -38 0 327 248.5)"/><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="e" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#000"><path d="M8 0L0-3v6z" fill="currentColor" stroke="currentColor"/></marker><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="j" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#000"><path d="M8 0H0m0-3l8 3-8 3" fill="none" stroke="currentColor"/></marker></defs><g fill="none"><circle cx="183" cy="109.5" r="19" fill="url(#b)"/><circle cx="183" cy="109.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><text transform="translate(172.8 100.5)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="4.72" y="15" textLength="10.96">R</tspan></text><circle cx="135" cy="160.5" r="19" fill="url(#c)"/><circle cx="135" cy="160.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="230.5" cy="160.5" r="19" fill="url(#d)"/><circle cx="230.5" cy="160.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M169.978 123.336l-15.171 16.119m41.143-16.051l14.853 15.948"/><circle cx="81.5" cy="215.5" r="19" fill="url(#f)"/><circle cx="81.5" cy="215.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M121.752 174.119l-20.101 20.665"/><circle cx="279.5" cy="216.5" r="19" fill="url(#g)"/><circle cx="279.5" cy="216.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="231.5" cy="267.5" r="19" fill="url(#h)"/><circle cx="231.5" cy="267.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="327" cy="267.5" r="19" fill="url(#i)"/><circle cx="327" cy="267.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><text transform="translate(316.8 258.5)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="5.016" y="15" textLength="10.368">A</tspan></text><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M243.012 174.799l17.457 19.951m31.981 35.654l14.853 15.948m-40.825-16.016l-15.171 16.119"/><text transform="translate(304.5 62)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x=".2" y="15" textLength="10.368">A</tspan><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="9.384" y="15" textLength="4.448">’</tspan><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="12.648" y="15" textLength="87.152">s immediate</tspan><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="13.544" y="33" textLength="72.912">dominator</tspan></text><path marker-end="url(#j)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="4,4" d="M341.863 103l-48.444 88.167"/></g></svg> \ No newline at end of file
diff --git a/devtools/docs/user/memory/dominators/memory-graph-unreachable.svg b/devtools/docs/user/memory/dominators/memory-graph-unreachable.svg
new file mode 100644
index 0000000000..62abb0e016
--- /dev/null
+++ b/devtools/docs/user/memory/dominators/memory-graph-unreachable.svg
@@ -0,0 +1,4 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" viewBox="60 88 287 200" width="287pt" height="200pt"><defs><linearGradient x1="0" x2="1" id="a" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#e5f2f2"/><stop offset="1" stop-color="#cff2f2"/></linearGradient><linearGradient id="c" xl:href="#a" gradientTransform="matrix(0 38 -38 0 183 90.5)"/><linearGradient id="d" xl:href="#a" gradientTransform="matrix(0 38 -38 0 135 141.5)"/><linearGradient id="e" xl:href="#a" gradientTransform="rotate(90 44.5 186) scale(38)"/><linearGradient x1="0" x2="1" id="b" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f29a8b"/><stop offset="1" stop-color="#f23d1c"/></linearGradient><linearGradient id="f" xl:href="#b" gradientTransform="rotate(90 41 237.5) scale(38)"/><linearGradient id="g" xl:href="#b" gradientTransform="rotate(90 -8.5 239) scale(38)"/><linearGradient id="h" xl:href="#b" gradientTransform="matrix(0 38 -38 0 326 247.5)"/><linearGradient id="j" xl:href="#a" gradientTransform="matrix(0 38 -38 0 81.5 196.5)"/><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="i" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#000"><path d="M8 0L0-3v6z" fill="currentColor" stroke="currentColor"/></marker></defs><g fill="none"><circle cx="183" cy="109.5" r="19" fill="url(#c)"/><circle cx="183" cy="109.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><text transform="translate(172.8 100.5)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="4.72" y="15" textLength="10.96">R</tspan></text><circle cx="135" cy="160.5" r="19" fill="url(#d)"/><circle cx="135" cy="160.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="230.5" cy="160.5" r="19" fill="url(#e)"/><circle cx="230.5" cy="160.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="278.5" cy="215.5" r="19" fill="url(#f)"/><circle cx="278.5" cy="215.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="230.5" cy="266.5" r="19" fill="url(#g)"/><circle cx="230.5" cy="266.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="326" cy="266.5" r="19" fill="url(#h)"/><circle cx="326" cy="266.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path marker-end="url(#i)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M169.978 123.336l-15.171 16.119m41.143-16.051l14.853 15.948m54.675 89.984l-15.171 16.119m41.143-16.051l14.853 15.948"/><circle cx="81.5" cy="215.5" r="19" fill="url(#j)"/><circle cx="81.5" cy="215.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path marker-end="url(#i)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M121.752 174.119l-20.101 20.665"/></g></svg> \ No newline at end of file
diff --git a/devtools/docs/user/memory/dominators/memory-graph.svg b/devtools/docs/user/memory/dominators/memory-graph.svg
new file mode 100644
index 0000000000..0b4ee2d64c
--- /dev/null
+++ b/devtools/docs/user/memory/dominators/memory-graph.svg
@@ -0,0 +1,4 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" viewBox="60 88 288 201" width="384" height="268"><defs><linearGradient x1="0" x2="1" id="a" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#e5f2f2"/><stop offset="1" stop-color="#cff2f2"/></linearGradient><linearGradient id="b" xl:href="#a" gradientTransform="matrix(0 38 -38 0 183 90.5)"/><linearGradient id="c" xl:href="#a" gradientTransform="matrix(0 38 -38 0 135 141.5)"/><linearGradient id="d" xl:href="#a" gradientTransform="rotate(90 44.5 186) scale(38)"/><linearGradient id="f" xl:href="#a" gradientTransform="matrix(0 38 -38 0 81.5 196.5)"/><linearGradient id="g" xl:href="#a" gradientTransform="rotate(90 41 238.5) scale(38)"/><linearGradient id="h" xl:href="#a" gradientTransform="rotate(90 -8.5 240) scale(38)"/><linearGradient id="i" xl:href="#a" gradientTransform="matrix(0 38 -38 0 327 248.5)"/><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="e" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#000"><path d="M8 0L0-3v6z" fill="currentColor" stroke="currentColor"/></marker></defs><g fill="none"><circle cx="183" cy="109.5" r="19" fill="url(#b)"/><circle cx="183" cy="109.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><text transform="translate(172.8 100.5)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="4.72" y="15" textLength="10.96">R</tspan></text><circle cx="135" cy="160.5" r="19" fill="url(#c)"/><circle cx="135" cy="160.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="230.5" cy="160.5" r="19" fill="url(#d)"/><circle cx="230.5" cy="160.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M169.978 123.336l-15.171 16.119m41.143-16.051l14.853 15.948"/><circle cx="81.5" cy="215.5" r="19" fill="url(#f)"/><circle cx="81.5" cy="215.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M121.752 174.119l-20.101 20.665"/><circle cx="279.5" cy="216.5" r="19" fill="url(#g)"/><circle cx="279.5" cy="216.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="231.5" cy="267.5" r="19" fill="url(#h)"/><circle cx="231.5" cy="267.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><circle cx="327" cy="267.5" r="19" fill="url(#i)"/><circle cx="327" cy="267.5" r="19" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path marker-end="url(#e)" stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M243.012 174.799l17.457 19.951m31.981 35.654l14.853 15.948m-40.825-16.016l-15.171 16.119"/></g></svg> \ No newline at end of file
diff --git a/devtools/docs/user/memory/dominators_view/dominators-1.png b/devtools/docs/user/memory/dominators_view/dominators-1.png
new file mode 100644
index 0000000000..163a80016c
--- /dev/null
+++ b/devtools/docs/user/memory/dominators_view/dominators-1.png
Binary files differ
diff --git a/devtools/docs/user/memory/dominators_view/dominators-10.png b/devtools/docs/user/memory/dominators_view/dominators-10.png
new file mode 100644
index 0000000000..e6688060af
--- /dev/null
+++ b/devtools/docs/user/memory/dominators_view/dominators-10.png
Binary files differ
diff --git a/devtools/docs/user/memory/dominators_view/dominators-2.png b/devtools/docs/user/memory/dominators_view/dominators-2.png
new file mode 100644
index 0000000000..99b7db7b09
--- /dev/null
+++ b/devtools/docs/user/memory/dominators_view/dominators-2.png
Binary files differ
diff --git a/devtools/docs/user/memory/dominators_view/dominators-3.png b/devtools/docs/user/memory/dominators_view/dominators-3.png
new file mode 100644
index 0000000000..2d380f6e21
--- /dev/null
+++ b/devtools/docs/user/memory/dominators_view/dominators-3.png
Binary files differ
diff --git a/devtools/docs/user/memory/dominators_view/dominators-4.png b/devtools/docs/user/memory/dominators_view/dominators-4.png
new file mode 100644
index 0000000000..d3d5eef59c
--- /dev/null
+++ b/devtools/docs/user/memory/dominators_view/dominators-4.png
Binary files differ
diff --git a/devtools/docs/user/memory/dominators_view/dominators-5.png b/devtools/docs/user/memory/dominators_view/dominators-5.png
new file mode 100644
index 0000000000..41a03488e9
--- /dev/null
+++ b/devtools/docs/user/memory/dominators_view/dominators-5.png
Binary files differ
diff --git a/devtools/docs/user/memory/dominators_view/dominators-6.png b/devtools/docs/user/memory/dominators_view/dominators-6.png
new file mode 100644
index 0000000000..a3d3026eb2
--- /dev/null
+++ b/devtools/docs/user/memory/dominators_view/dominators-6.png
Binary files differ
diff --git a/devtools/docs/user/memory/dominators_view/dominators-7.png b/devtools/docs/user/memory/dominators_view/dominators-7.png
new file mode 100644
index 0000000000..160f205391
--- /dev/null
+++ b/devtools/docs/user/memory/dominators_view/dominators-7.png
Binary files differ
diff --git a/devtools/docs/user/memory/dominators_view/dominators-8.png b/devtools/docs/user/memory/dominators_view/dominators-8.png
new file mode 100644
index 0000000000..e9512b9b05
--- /dev/null
+++ b/devtools/docs/user/memory/dominators_view/dominators-8.png
Binary files differ
diff --git a/devtools/docs/user/memory/dominators_view/dominators-9.png b/devtools/docs/user/memory/dominators_view/dominators-9.png
new file mode 100644
index 0000000000..af396abc21
--- /dev/null
+++ b/devtools/docs/user/memory/dominators_view/dominators-9.png
Binary files differ
diff --git a/devtools/docs/user/memory/dominators_view/index.rst b/devtools/docs/user/memory/dominators_view/index.rst
new file mode 100644
index 0000000000..a0e2c9db87
--- /dev/null
+++ b/devtools/docs/user/memory/dominators_view/index.rst
@@ -0,0 +1,174 @@
+===============
+Dominators view
+===============
+
+The Dominators view is new in Firefox 46.
+
+Starting in Firefox 46, the Memory tool includes a new view called the Dominators view. This is useful for understanding the "retained size" of objects allocated by your site: that is, the size of the objects themselves plus the size of the objects that they keep alive through references.
+
+If you already know what shallow size, retained size, and dominators are, skip to the Dominators UI section. Otherwise, you might want to review the article on :doc:`Dominators concepts <../dominators/index>`.
+
+
+Dominators UI
+*************
+
+To see the Dominators view for a snapshot, select "Dominators" in the "View" drop-down list. It looks something like this:
+
+.. image:: dominators-1.png
+ :class: center
+
+The Dominators view consists of two panels:
+
+- the :ref:`Dominators Tree panel <memory-dominators-view-dominators-tree-panel>` shows you which nodes in the snapshot are retaining the most memory
+- the :ref:`Retaining Paths panel <memory-dominators-view-retaining-paths-panel>` (new in Firefox 47) shows the 5 shortest retaining paths for a single node.
+
+.. image:: dominators-2.png
+ :class: center
+
+
+.. _memory-dominators-view-dominators-tree-panel:
+
+Dominators Tree panel
+*********************
+
+The Dominators Tree tells you which objects in the snapshot are retaining the most memory.
+
+In the main part of the UI, the first row is labeled "GC Roots". Immediately underneath that is an entry for:
+
+
+- Every GC root node. In Gecko, there is more than one memory graph, and therefore more than one root. There may be many (often temporary) roots. For example: variables allocated on the stack need to be rooted, or internal caches may need to root their elements.
+- Any other node that's referenced from two different roots (since in this case, neither root dominates it).
+
+
+Each entry displays:
+
+
+- the retained size of the node, as bytes and as a percentage of the total
+- the shallow size of the node, as bytes and as a percentage of the total
+- the nodes's name and address in memory.
+
+
+Entries are ordered by the amount of memory that they retain. For example:
+
+.. image:: dominators-3.png
+ :class: center
+
+In this screenshot we can see five entries under "GC Roots". The first two are Call and Window objects, and retain about 21% and 8% of the total size of the memory snapshot, respectively. You can also see that these objects have a relatively tiny "Shallow Size", so almost all of the retained size is in the objects that they dominate.
+
+Immediately under each GC root, you'll see all the nodes for which this root is the :ref:`immediate dominator <memory-dominators-immediate-dominator>`. These nodes are also ordered by their retained size.
+
+For example, if we click on the first Window object:
+
+.. image:: dominators-4.png
+ :class: center
+
+We can see that this Window dominates a CSS2Properties object, whose retained size is 2% of the total snapshot size. Again the shallow size is very small: almost all of its retained size is in the nodes that it dominates. By clicking on the disclosure arrow next to the Function, we can see those nodes.
+
+In this way you can quickly get a sense of which objects retain the most memory in the snapshot.
+
+You can use :kbd:`Alt` + :kbd:`click` to expand the whole graph under a node.
+
+Call Stack
+**********
+
+In the toolbar at the top of the tool is a dropdown called "Label by":
+
+.. image:: dominators-5.png
+ :class: center
+
+By default, this is set to "Type". However, you can set it instead to "Call Stack" to see exactly where in your code the objects are being allocated.
+
+.. note::
+
+ This option is called "Allocation Stack" in Firefox 46.
+
+
+To enable this, you must check the box labeled "Record call stacks" *before* you run the code that allocates the objects. Then take a snapshot, then select "Call Stack" in the "Label by" drop-down.
+
+Now the node's name will contain the name of the function that allocated it, and the file, line number and character position of the exact spot where the function allocated it. Clicking the file name will take you to that spot in the Debugger.
+
+
+.. note::
+
+ Sometimes you'll see "(no stack available)" here. In particular, allocation stacks are currently only recorded for objects, not for arrays, strings, or internal structures.
+
+
+.. _memory-dominators-view-retaining-paths-panel:
+
+Retaining Paths panel
+*********************
+
+The Retaining Paths panel is new in Firefox 47.
+
+The Retaining Paths panel shows you, for a given node, the 5 shortest paths back from this node to a GC root. This enables you to see all the nodes that are keeping the given node from being garbage-collected. If you suspect that an object is being leaked, this will show you exactly which objects are holding a reference to it.
+
+To see the retaining paths for a node, you have to select the node in the Dominators Tree panel:
+
+.. image:: dominators-6.png
+ :class: center
+
+
+Here, we've selected an object, and can see a single path back to a GC root.
+
+The ``Window`` GC root holds a reference to an ``HTMLDivElement`` object, and that holds a reference to an ``Object``, and so on. If you look in the Dominators Tree panel, you can trace the same path there. If either of these references were removed, the items below them could be garbage-collected.
+
+Each connection in the graph is labeled with the variable name for the referenced object.
+
+Sometimes there's more than one retaining path back from a node:
+
+.. image:: dominators-7.png
+ :class: center
+
+
+Here there are three paths back from the ``DocumentPrototype`` node to a GC root. If one were removed, then the ``DocumentPrototype`` would still not be garbage-collected, because it's still retained by the other two path.
+
+
+Example
+*******
+
+Let's see how some simple code is reflected in the Dominators view.
+
+We'll use the :doc:`monster allocation example <../monster_example/index>`, which creates three arrays, each containing 5000 monsters, each monster having a randomly-generated name.
+
+Taking a snapshot
+*****************
+
+To see what it looks like in the Dominators view:
+
+- load the page
+- enable the Memory tool in the :ref:`Settings <tool-toolbox-settings>`, if you haven't already
+- open the Memory tool
+- check "Record call stacks"
+- press the button labeled "Make monsters!"
+- take a snapshot
+- switch to the "Dominators" view
+
+
+Analyzing the Dominators Tree
+*****************************
+
+You'll see the three arrays as the top three GC roots, each retaining about 23% of the total memory usage:
+
+.. image:: dominators-8.png
+ :class: center
+
+
+If you expand an array, you'll see the objects (monsters) it contains. Each monster has a relatively small shallow size of 160 bytes. This includes the integer eye- and tentacle-counts. Each monster has a bigger retained size, which is accounted for by the string used for the monster's name:
+
+.. image:: dominators-9.png
+ :class: center
+
+All this maps closely to the :ref:`memory graph we were expecting to see <memory-dominators-immediate-dominator>`. One thing you might be wondering, though, is: where's the top-level object that retains all three arrays? If we look at the Retaining Paths panel for one of the arrays, we'll see it:
+
+.. image:: dominators-10.png
+ :class: center
+
+Here we can see the retaining object, and even that this particular array is the array of ``fierce`` monsters. But the array is also rooted directly, so if the object were to stop referencing the array, it would still not be eligible for garbage collection.
+
+This means that the object does not dominate the array, and is therefore not shown in the Dominators Tree view. :ref:`See the relevant section of the Dominators concepts article <memory-dominators-multiple-paths>`.
+
+
+Using the Call Stack view
+*************************
+
+Finally, you can switch to the Call Stack view, see where the objects are being allocated, and jump to that point in the Debugger.
diff --git a/devtools/docs/user/memory/index.rst b/devtools/docs/user/memory/index.rst
new file mode 100644
index 0000000000..7a508015a1
--- /dev/null
+++ b/devtools/docs/user/memory/index.rst
@@ -0,0 +1,52 @@
+======
+Memory
+======
+
+The Memory tool lets you take a snapshot of the current tab's memory `heap <https://en.wikipedia.org/wiki/Memory_management#HEAP>`_. It then provides a number of views of the heap that can show you which objects account for memory usage and exactly where in your code you are allocating memory.
+
+.. raw:: html
+
+ <iframe width="560" height="315" src="https://www.youtube.com/embed/DJLoq5E5ww0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
+ <br/>
+ <br/>
+
+
+The basics
+**********
+
+- :ref:`Opening the memory tool <memory-basic-operations-opening-the-memory-tool>`
+- :ref:`Taking a heap snapshot <memory-basic-operations-taking-a-heap-snapshot>`
+- :ref:`Comparing two snapshots <memory-basic-operations-comparing-snapshots>`
+- :ref:`Deleting snapshots <memory-basic-operations-clearing-a-snapshot>`
+- :ref:`Saving and loading snapshots <memory-basic-operations-saving-and-loading-snapshots>`
+- :ref:`Recording call stacks <memory-basic-operations-recording-call-stacks>`
+
+
+Analyzing snapshots
+*******************
+
+The Tree map view is new in Firefox 48, and the Dominators view is new in Firefox 46.
+
+Once you've taken a snapshot, there are three main views the Memory tool provides:
+
+
+- :doc:`the Tree map view <tree_map_view/index>` shows memory usage as a `treemap <https://en.wikipedia.org/wiki/Treemapping>`_.
+- :doc:`the Aggregate view <aggregate_view/index>` shows memory usage as a table of allocated types.
+- :doc:`the Dominators view <dominators_view/index>` shows the "retained size" of objects: that is, the size of objects plus the size of other objects that they keep alive through references.
+
+
+If you've opted to record allocation stacks for the snapshot, the Aggregate and Dominators views can show you exactly where in your code allocations are happening.
+
+Concepts
+********
+
+- :doc:`Dominators <dominators_view/index>`
+
+
+Example pages
+*************
+
+Examples used in the Memory tool documentation.
+
+- :doc:`Monster example <monster_example/index>`
+- :doc:`DOM allocation example <dom_allocation_example/index>`
diff --git a/devtools/docs/user/memory/monster_example/index.rst b/devtools/docs/user/memory/monster_example/index.rst
new file mode 100644
index 0000000000..93042541a1
--- /dev/null
+++ b/devtools/docs/user/memory/monster_example/index.rst
@@ -0,0 +1,80 @@
+===============
+Monster example
+===============
+
+This article describes a very simple web page that we'll use to illustrate some features of the Memory tool.
+
+You can try the site at https://firefox-devtools.github.io/performance-scenarios/js-allocs/alloc.html. Here's the code:
+
+.. code-block:: javascript
+
+ var MONSTER_COUNT = 5000;
+ var MIN_NAME_LENGTH = 2;
+ var MAX_NAME_LENGTH = 48;
+
+ function Monster() {
+
+ function randomInt(min, max) {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+ }
+
+ function randomName() {
+ var chars = "abcdefghijklmnopqrstuvwxyz";
+ var nameLength = randomInt(MIN_NAME_LENGTH, MAX_NAME_LENGTH);
+ var name = "";
+ for (var j = 0; j &amp;lt; nameLength; j++) {
+ name += chars[randomInt(0, chars.length-1)];
+ }
+ return name;
+ }
+
+ this.name = randomName();
+ this.eyeCount = randomInt(0, 25);
+ this.tentacleCount = randomInt(0, 250);
+ }
+
+ function makeMonsters() {
+ var monsters = {
+ "friendly": [],
+ "fierce": [],
+ "undecided": []
+ };
+
+ for (var i = 0; i < MONSTER_COUNT; i++) {
+ monsters.friendly.push(new Monster());
+ }
+
+ for (var i = 0; i < MONSTER_COUNT; i++) {
+ monsters.fierce.push(new Monster());
+ }
+
+ for (var i = 0; i < MONSTER_COUNT; i++) {
+ monsters.undecided.push(new Monster());
+ }
+
+ console.log(monsters);
+ }
+
+ var makeMonstersButton = document.getElementById("make-monsters");
+ makeMonstersButton.addEventListener("click", makeMonsters);
+
+The page contains a button: when you push the button, the code creates some monsters. Specifically:
+
+
+- the code creates an object with three properties, each an array:
+
+ - one for fierce monsters
+ - one for friendly monsters
+ - one for monsters who haven't decided yet.
+
+
+- for each array, the code creates and appends 5000 randomly-initialized monsters. Each monster has:
+
+ - a string, for the monster's name
+ - a number representing the number of eyes it has
+ - a number representing the number of tentacles it has.
+
+So the structure of the memory allocated on the JavaScript heap is an object containing three arrays, each containing 5000 objects (monsters), each object containing a string and two integers:
+
+.. image:: monsters.svg
+ :class: center
diff --git a/devtools/docs/user/memory/monster_example/monsters.svg b/devtools/docs/user/memory/monster_example/monsters.svg
new file mode 100644
index 0000000000..1ecb9b1f77
--- /dev/null
+++ b/devtools/docs/user/memory/monster_example/monsters.svg
@@ -0,0 +1,4 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" viewBox="62 78 464 484" width="464pt" height="484pt"><defs><linearGradient x1="0" x2="1" id="a" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#e5f2f2"/><stop offset="1" stop-color="#cff2f2"/></linearGradient><linearGradient id="b" xl:href="#a" gradientTransform="matrix(0 31.5 -31.5 0 103.25 304)"/><linearGradient id="c" xl:href="#a" gradientTransform="matrix(0 31.5 -31.5 0 231.25 136)"/><linearGradient id="d" xl:href="#a" gradientTransform="matrix(0 31.5 -31.5 0 359.25 136)"/><linearGradient id="e" xl:href="#a" gradientTransform="matrix(0 31.5 -31.5 0 359.25 80)"/><linearGradient id="f" xl:href="#a" gradientTransform="matrix(0 31.5 -31.5 0 359.25 192)"/><linearGradient id="g" xl:href="#a" gradientTransform="matrix(0 31.5 -31.5 0 484.75 81)"/><linearGradient id="h" xl:href="#a" gradientTransform="matrix(0 31.5 -31.5 0 484.75 136)"/><linearGradient id="j" xl:href="#a" gradientTransform="matrix(0 31.5 -31.5 0 231.25 304)"/><linearGradient id="k" xl:href="#a" gradientTransform="matrix(0 31.5 -31.5 0 359.25 304)"/><linearGradient id="l" xl:href="#a" gradientTransform="matrix(0 31.5 -31.5 0 359.25 248)"/><linearGradient id="m" xl:href="#a" gradientTransform="matrix(0 31.5 -31.5 0 359.25 360)"/><linearGradient id="n" xl:href="#a" gradientTransform="matrix(0 31.5 -31.5 0 484.75 249)"/><linearGradient id="o" xl:href="#a" gradientTransform="matrix(0 31.5 -31.5 0 484.75 304)"/><linearGradient id="p" xl:href="#a" gradientTransform="matrix(0 31.5 -31.5 0 231.25 472)"/><linearGradient id="q" xl:href="#a" gradientTransform="matrix(0 31.5 -31.5 0 359.25 472)"/><linearGradient id="r" xl:href="#a" gradientTransform="matrix(0 31.5 -31.5 0 359.25 416)"/><linearGradient id="s" xl:href="#a" gradientTransform="matrix(0 31.5 -31.5 0 359.25 528)"/><linearGradient id="t" xl:href="#a" gradientTransform="matrix(0 31.5 -31.5 0 484.75 417)"/><linearGradient id="u" xl:href="#a" gradientTransform="matrix(0 31.5 -31.5 0 484.75 472)"/><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="i" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#000"><path d="M8 0L0-3v6z" fill="currentColor" stroke="currentColor"/></marker></defs><g fill="none"><path fill="url(#b)" d="M64.5 304H142v31.5H64.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M64.5 304H142v31.5H64.5z"/><text transform="translate(69.5 310.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="10.038" y="15" textLength="47.424">Object</tspan></text><path fill="url(#c)" d="M192.5 136H270v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M192.5 136H270v31.5h-77.5z"/><text transform="translate(197.5 142.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="14.942" y="15" textLength="37.616">Array</tspan></text><path fill="url(#d)" d="M320.5 136H398v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M320.5 136H398v31.5h-77.5z"/><text transform="translate(325.5 142.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="4.262" y="15" textLength="58.976">Monster</tspan></text><path fill="url(#e)" d="M320.5 80H398v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M320.5 80H398v31.5h-77.5z"/><text transform="translate(325.5 86.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="4.262" y="15" textLength="58.976">Monster</tspan></text><path fill="url(#f)" d="M320.5 192H398v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M320.5 192H398v31.5h-77.5z"/><text transform="translate(325.5 198.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="25.75" y="15" textLength="16">…</tspan></text><path fill="url(#g)" d="M446 81h77.5v31.5H446z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M446 81h77.5v31.5H446z"/><text transform="translate(451 87.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="12.566" y="15" textLength="42.368">String</tspan></text><path fill="url(#h)" d="M446 136h77.5v31.5H446z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M446 136h77.5v31.5H446z"/><text transform="translate(451 142.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="12.566" y="15" textLength="42.368">String</tspan></text><path d="M103.25 304V151.75h79.35m112.65 0h15.35m-15.35 0v-56h15.35m-40.6 56h25.25v56h15.35m87.4-112l38.101.439M398 151.75h38.1" marker-end="url(#i)" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path fill="url(#j)" d="M192.5 304H270v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M192.5 304H270v31.5h-77.5z"/><text transform="translate(197.5 310.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="14.942" y="15" textLength="37.616">Array</tspan></text><path fill="url(#k)" d="M320.5 304H398v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M320.5 304H398v31.5h-77.5z"/><text transform="translate(325.5 310.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="4.262" y="15" textLength="58.976">Monster</tspan></text><path fill="url(#l)" d="M320.5 248H398v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M320.5 248H398v31.5h-77.5z"/><text transform="translate(325.5 254.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="4.262" y="15" textLength="58.976">Monster</tspan></text><path fill="url(#m)" d="M320.5 360H398v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M320.5 360H398v31.5h-77.5z"/><text transform="translate(325.5 366.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="25.75" y="15" textLength="16">…</tspan></text><path fill="url(#n)" d="M446 249h77.5v31.5H446z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M446 249h77.5v31.5H446z"/><text transform="translate(451 255.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="12.566" y="15" textLength="42.368">String</tspan></text><path fill="url(#o)" d="M446 304h77.5v31.5H446z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M446 304h77.5v31.5H446z"/><text transform="translate(451 310.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="12.566" y="15" textLength="42.368">String</tspan></text><path d="M142 319.75h40.6m112.65 0h15.35m-15.35 0v-56h15.35m-40.6 56h25.25v56h15.35m87.4-112l38.101.439M398 319.75h38.1" marker-end="url(#i)" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/><path fill="url(#p)" d="M192.5 472H270v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M192.5 472H270v31.5h-77.5z"/><text transform="translate(197.5 478.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="14.942" y="15" textLength="37.616">Array</tspan></text><path fill="url(#q)" d="M320.5 472H398v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M320.5 472H398v31.5h-77.5z"/><text transform="translate(325.5 478.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="4.262" y="15" textLength="58.976">Monster</tspan></text><path fill="url(#r)" d="M320.5 416H398v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M320.5 416H398v31.5h-77.5z"/><text transform="translate(325.5 422.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="4.262" y="15" textLength="58.976">Monster</tspan></text><path fill="url(#s)" d="M320.5 528H398v31.5h-77.5z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M320.5 528H398v31.5h-77.5z"/><text transform="translate(325.5 534.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="25.75" y="15" textLength="16">…</tspan></text><path fill="url(#t)" d="M446 417h77.5v31.5H446z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M446 417h77.5v31.5H446z"/><text transform="translate(451 423.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="12.566" y="15" textLength="42.368">String</tspan></text><path fill="url(#u)" d="M446 472h77.5v31.5H446z"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" d="M446 472h77.5v31.5H446z"/><text transform="translate(451 478.75)" fill="#000"><tspan font-family="Helvetica Neue" font-size="16" font-weight="500" x="12.566" y="15" textLength="42.368">String</tspan></text><path d="M103.25 335.5v152.25h79.35m112.65 0h15.35m-15.35 0v-56h15.35m-40.6 56h25.25v56h15.35m87.4-112l38.101.439M398 487.75h38.1" marker-end="url(#i)" stroke="#000" stroke-linecap="round" stroke-linejoin="round"/></g></svg> \ No newline at end of file
diff --git a/devtools/docs/user/memory/tree_map_view/index.rst b/devtools/docs/user/memory/tree_map_view/index.rst
new file mode 100644
index 0000000000..3ab11d733b
--- /dev/null
+++ b/devtools/docs/user/memory/tree_map_view/index.rst
@@ -0,0 +1,47 @@
+=============
+Tree map view
+=============
+
+The Tree map view is new in Firefox 48.
+
+The Tree map view provides a visual representation of the snapshot, that helps you quickly get an idea of which objects are using the most memory.
+
+A treemap displays `"hierarchical (tree-structured) data as a set of nested rectangles" <https://en.wikipedia.org/wiki/Treemapping>`_. The size of the rectangles corresponds to some quantitative aspect of the data.
+
+For the treemaps shown in the Memory tool, things on the heap are divided at the top level into four categories:
+
+
+- **objects**: JavaScript and DOM objects, such as `Function <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function>`_, `Object <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object>`_, or `Array <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array>`_, and DOM types like `Window <https://developer.mozilla.org/en-US/docs/Web/API/Window>`_ and `HTMLDivElement <https://developer.mozilla.org/en-US/docs/Web/API/HTMLDivElement>`_.
+- **scripts**: JavaScript sources loaded by the page.
+- **strings**
+- **other**: this includes internal `SpiderMonkey <https://spidermonkey.dev/>`_ objects.
+
+
+Each category is represented with a rectangle, and the size of the rectangle corresponds to the proportion of the heap occupied by items in that category. This means you can quickly get an idea of roughly what sorts of things allocated by your site are using the most memory.
+
+Within top-level categories:
+
+
+- **objects** is further divided by the object's type.
+- **scripts** is further subdivided by the script's origin. It also includes a separate rectangle for code that can't be correlated with a file, such as JIT-optimized code.
+- **other** is further subdivided by the object's type.
+
+
+Here are some example snapshots, as they appear in the Tree map view:
+
+.. image:: treemap-domnodes.png
+ :class: center
+
+
+This treemap is from the :doc:`DOM allocation example <../dom_allocation_example/index>`, which runs a script that creates a large number of DOM nodes (200 `HTMLDivElement <https://developer.mozilla.org/en-US/docs/Web/API/HTMLDivElement>`_ objects and 4000 `HTMLSpanElement <https://developer.mozilla.org/en-US/docs/Web/API/HTMLSpanElement>`_ objects). You can see how almost all the heap usage is from the ``HTMLSpanElement`` objects that it creates.
+
+.. image:: treemap-monsters.png
+ :class: center
+
+
+This treemap is from the :doc:`monster allocation example <../monster_example/index>`, which creates three arrays, each containing 5000 monsters, each monster having a randomly-generated name. You can see that most of the heap is occupied by the strings used for the monsters' names, and the objects used to contain the monsters' other attributes.
+
+.. image:: treemap-bbc.png
+ :class: center
+
+This treemap is from http://www.bbc.com/, and is probably more representative of real life than the examples. You can see the much larger proportion of the heap occupied by scripts, that are loaded from a large number of origins.
diff --git a/devtools/docs/user/memory/tree_map_view/treemap-bbc.png b/devtools/docs/user/memory/tree_map_view/treemap-bbc.png
new file mode 100644
index 0000000000..55552b8382
--- /dev/null
+++ b/devtools/docs/user/memory/tree_map_view/treemap-bbc.png
Binary files differ
diff --git a/devtools/docs/user/memory/tree_map_view/treemap-domnodes.png b/devtools/docs/user/memory/tree_map_view/treemap-domnodes.png
new file mode 100644
index 0000000000..1192e390da
--- /dev/null
+++ b/devtools/docs/user/memory/tree_map_view/treemap-domnodes.png
Binary files differ
diff --git a/devtools/docs/user/memory/tree_map_view/treemap-monsters.png b/devtools/docs/user/memory/tree_map_view/treemap-monsters.png
new file mode 100644
index 0000000000..513adab923
--- /dev/null
+++ b/devtools/docs/user/memory/tree_map_view/treemap-monsters.png
Binary files differ