支配者

本文介绍了可达性浅层保留大小以及支配者的概念,这些概念适用于 JavaScript 等垃圾收集语言。

这些概念在内存分析中很重要,因为对象本身可能很小,但可能持有对其他更大对象的引用,并且通过这样做会阻止垃圾回收器释放额外的内存。

您可以使用内存工具中的支配者视图查看页面中的支配者。

在像 JavaScript 这样的垃圾收集语言中,程序员通常不必担心释放内存。他们可以创建和使用对象,当不再需要对象时,运行时负责清理并释放对象占用的内存。

可达性

在现代 JavaScript 实现中,运行时根据可达性来决定对象是否不再需要。在这个系统中,堆表示为一个或多个图。图中的每个节点表示一个对象,节点之间的每个连接(边)表示从一个对象到另一个对象的引用。图从一个根节点开始,在这些图中用“R”表示。

../../../_images/memory-graph.svg

在垃圾回收期间,运行时遍历图,从根节点开始,并标记它找到的每个对象。它找不到的任何对象都是不可达的,并且可以被释放。

因此,当一个对象变得不可达(例如,因为它只被一个超出作用域的单个局部变量引用)时,它引用的任何对象也变得不可达,只要没有其他对象引用它们。

../../../_images/memory-graph-unreachable.svg

相反,这意味着只要其他可达对象持有对它们的引用,对象就会保持活动状态。

浅层和保留大小

这产生了两种看待对象大小的方法之间的区别

  • 浅层大小:对象本身的大小

  • 保留大小:对象本身的大小,加上此对象保持活动状态的其他对象的大小

通常,对象将具有较小的浅层大小,但通过它们包含的对其他对象的引用,具有更大的保留大小。保留大小是分析内存使用情况中的一个重要概念,因为它回答了“如果此对象不再存在,将释放多少内存?”的问题。

支配者

一个相关的概念是支配者。如果从根节点到 A 的每条路径都经过 B,则称节点 B 支配节点 A。

../../../_images/memory-graph-dominators.svg

如果 A 的任何支配者被释放,则节点 A 本身就会有资格进行垃圾回收。

如果节点 B 支配节点 A,但不支配 A 的任何其他支配者,则 B 是 A 的直接支配者

../../../_images/memory-graph-immediate-dominator.svg

这里有一个细微差别,如果对象 A 被另外两个不相关的对象 B 和 C 引用,则这两个对象都不是它的支配者,因为您可以从图中删除 B 或 C,而 A 仍然会被其其他引用者保留。相反,A 的直接支配者将是它的第一个公共祖先。

../../../_images/memory-graph-dominator-multiple-references.svg

另请参阅