diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /docs/performance/memory/dominators.md | |
parent | Initial commit. (diff) | |
download | firefox-esr-upstream.tar.xz firefox-esr-upstream.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'docs/performance/memory/dominators.md')
-rw-r--r-- | docs/performance/memory/dominators.md | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/docs/performance/memory/dominators.md b/docs/performance/memory/dominators.md new file mode 100644 index 0000000000..e64c465e62 --- /dev/null +++ b/docs/performance/memory/dominators.md @@ -0,0 +1,90 @@ +# 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 [Dominators +view](dominators_view.md) 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. + +## 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\". + +![](../img/memory-graph.svg) + +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: + +![](../img/memory-graph-unreachable.svg) + +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 + +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: + +![](../img/memory-graph-dominators.svg) + +If any of node A\'s dominators are freed, then node A itself becomes +eligible for garbage collection. + +[If node B dominates node A, but does not dominate any of A\'s other +dominators, then B is the *immediate dominator* of +A:] + +![](../img/memory-graph-immediate-dominator.svg) + +[One slight subtlety here is that if an object A is referenced by two +other 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:\ +![](../img/memory-graph-dominator-multiple-references.svg) + +## 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). |