tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

index.rst (7731B)


      1 ===============
      2 Dominators view
      3 ===============
      4 
      5 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.
      6 
      7 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>`.
      8 
      9 
     10 Dominators UI
     11 *************
     12 
     13 To see the Dominators view for a snapshot, select "Dominators" in the "View" drop-down list. It looks something like this:
     14 
     15 .. image:: dominators-1.png
     16  :class: center
     17 
     18 The Dominators view consists of two panels:
     19 
     20 - the :ref:`Dominators Tree panel <memory-dominators-view-dominators-tree-panel>` shows you which nodes in the snapshot are retaining the most memory
     21 - the :ref:`Retaining Paths panel <memory-dominators-view-retaining-paths-panel>` shows the 5 shortest retaining paths for a single node.
     22 
     23 .. image:: dominators-2.png
     24  :class: center
     25 
     26 
     27 .. _memory-dominators-view-dominators-tree-panel:
     28 
     29 Dominators Tree panel
     30 *********************
     31 
     32 The Dominators Tree tells you which objects in the snapshot are retaining the most memory.
     33 
     34 In the main part of the UI, the first row is labeled "GC Roots". Immediately underneath that is an entry for:
     35 
     36 
     37 - 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.
     38 - Any other node that's referenced from two different roots (since in this case, neither root dominates it).
     39 
     40 
     41 Each entry displays:
     42 
     43 
     44 - the retained size of the node, as bytes and as a percentage of the total
     45 - the shallow size of the node, as bytes and as a percentage of the total
     46 - the nodes's name and address in memory.
     47 
     48 
     49 Entries are ordered by the amount of memory that they retain. For example:
     50 
     51 .. image:: dominators-3.png
     52  :class: center
     53 
     54 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.
     55 
     56 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.
     57 
     58 For example, if we click on the first Window object:
     59 
     60 .. image:: dominators-4.png
     61  :class: center
     62 
     63 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.
     64 
     65 In this way you can quickly get a sense of which objects retain the most memory in the snapshot.
     66 
     67 You can use :kbd:`Alt` + :kbd:`click` to expand the whole graph under a node.
     68 
     69 Call Stack
     70 **********
     71 
     72 In the toolbar at the top of the tool is a dropdown called "Label by":
     73 
     74 .. image:: dominators-5.png
     75  :class: center
     76 
     77 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.
     78 
     79 
     80 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.
     81 
     82 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.
     83 
     84 
     85 .. note::
     86 
     87  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.
     88 
     89 
     90 .. _memory-dominators-view-retaining-paths-panel:
     91 
     92 Retaining Paths panel
     93 *********************
     94 
     95 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.
     96 
     97 To see the retaining paths for a node, you have to select the node in the Dominators Tree panel:
     98 
     99 .. image:: dominators-6.png
    100  :class: center
    101 
    102 
    103 Here, we've selected an object, and can see a single path back to a GC root.
    104 
    105 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.
    106 
    107 Each connection in the graph is labeled with the variable name for the referenced object.
    108 
    109 Sometimes there's more than one retaining path back from a node:
    110 
    111 .. image:: dominators-7.png
    112  :class: center
    113 
    114 
    115 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.
    116 
    117 
    118 Example
    119 *******
    120 
    121 Let's see how some simple code is reflected in the Dominators view.
    122 
    123 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.
    124 
    125 Taking a snapshot
    126 *****************
    127 
    128 To see what it looks like in the Dominators view:
    129 
    130 - load the page
    131 - enable the Memory tool in the :ref:`Settings <tool-toolbox-settings>`, if you haven't already
    132 - open the Memory tool
    133 - check "Record call stacks"
    134 - press the button labeled "Make monsters!"
    135 - take a snapshot
    136 - switch to the "Dominators" view
    137 
    138 
    139 Analyzing the Dominators Tree
    140 *****************************
    141 
    142 You'll see the three arrays as the top three GC roots, each retaining about 23% of the total memory usage:
    143 
    144 .. image:: dominators-8.png
    145  :class: center
    146 
    147 
    148 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:
    149 
    150 .. image:: dominators-9.png
    151  :class: center
    152 
    153 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:
    154 
    155 .. image:: dominators-10.png
    156  :class: center
    157 
    158 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.
    159 
    160 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>`.
    161 
    162 
    163 Using the Call Stack view
    164 *************************
    165 
    166 Finally, you can switch to the Call Stack view, see where the objects are being allocated, and jump to that point in the Debugger.