index.rst (8386B)
1 ============== 2 Aggregate view 3 ============== 4 5 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:": 6 7 .. image:: memory-tool-switch-view.png 8 :class: center 9 10 11 The Aggregate view looks something like this: 12 13 .. image:: memory-tool-aggregate-view.png 14 :class: center 15 16 17 It presents a breakdown of the heap's contents, as a table. There are three main ways to group the data: 18 19 20 - :ref:`Type <memory-aggregate-view-type>` 21 - :ref:`Call Stack <memory-aggregate-view-call-stack>` 22 - :ref:`Inverted Call Stack <memory-aggregate-view-inverted-call-stack>` 23 24 You can switch between them using the dropdown menu labeled "Group by:" located at the top of the panel: 25 26 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. 27 28 29 .. _memory-aggregate-view-type: 30 31 Type 32 **** 33 34 This is the default view, which looks something like this: 35 36 .. image:: memory-tool-aggregate-view.png 37 :class: center 38 39 It groups the things on the heap into types, including: 40 41 42 - **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>`_ 43 - **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>`_ 44 - **Strings:** listed as ``"strings"`` 45 - **JavaScript sources:** listed as "``JSScript"`` 46 - **Internal objects:** such as "``js::Shape``". These are prefixed with ``"js::"``. 47 48 49 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. 50 51 52 - The "Total Count" column shows you the number of objects of each category that are currently allocated. 53 - 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. 54 55 56 The screenshots in this section are taken from a snapshot of the :doc:`monster example page <../monster_example/index>`. 57 58 59 For example, in the screenshot above, you can see that: 60 61 - there are four ``Array`` objects 62 - that account for 15% of the total heap. 63 64 65 Next to the type's name, there's an icon that contains three stars arranged in a triangle: 66 67 .. image:: memory-tool-in-group-icon.png 68 :class: center 69 70 71 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: 72 73 .. image:: memory-tool-in-group.png 74 :class: center 75 76 77 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). 78 79 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: 80 81 .. image:: memory-tool-in-group-retaining-paths.png 82 :class: center 83 84 85 .. _memory-aggregate-view-call-stack: 86 87 Call Stack 88 ********** 89 90 The Call Stack shows you exactly where in your code you are making heap allocations. 91 92 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. 93 94 You'll then see a list of all the functions that allocated objects, ordered by the size of the allocations they made: 95 96 .. image:: memory-tool-call-stack.png 97 :class: center 98 99 100 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: 101 102 103 - 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** 104 105 106 We can use the disclosure triangle to drill down the call tree, to find the exact place your code made those allocations. 107 108 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). 109 110 Let's get an allocation trace: 111 112 113 1. open the Memory tool 114 2. check "Record call stacks" 115 3. load https://firefox-devtools.github.io/performance-scenarios/dom-allocs/alloc.html 116 4. take a snapshot 117 5. select "View/Aggregate" 118 6. select "Group by/Call Stack" 119 120 .. raw:: html 121 122 <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> 123 <br/> 124 <br/> 125 126 You should see something like this: 127 128 .. image:: memory-tool-call-stack.png 129 :class: center 130 131 132 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). 133 134 We can use the disclosure arrow to expand the tree to find out exactly where we're allocating memory: 135 136 .. image:: memory-tool-call-stack-expanded.png 137 :class: center 138 139 140 This is where the "Bytes" and "Count" columns are useful: they show allocation size and number of allocations at that exact point. 141 142 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. 143 144 The file name and line number is a link: if we click it, we go directly to that line in the debugger: 145 146 .. raw:: html 147 148 <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> 149 <br/> 150 <br/> 151 152 153 .. _memory-aggregate-view-inverted-call-stack: 154 155 Inverted Call Stack 156 ******************* 157 158 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. 159 160 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. 161 162 Let's see what the example looks like when we select "Inverted Call Stack": 163 164 .. image:: memory-tool-inverted-call-stack.png 165 :class: center 166 167 168 Now at the top we can immediately see the ``createToolbarButton()`` call accounting for 89% of the heap usage in our page. 169 170 171 (no stack available) 172 ******************** 173 174 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. 175 176 For example: 177 178 179 - any scripts the page loads occupy heap space 180 - 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. 181 182 183 Many real-world pages will have a much higher "(no stack available)" share than 7%.