聚合视图¶
在 Firefox 48 之前,这是堆快照的默认视图。Firefox 48 之后,默认视图是 树状图视图,您可以使用标记为“视图:”的下拉菜单切换到聚合视图。
聚合视图看起来像这样
它以表格形式显示堆内容的细分。有三种主要方法可以对数据进行分组
类型
调用栈
反向调用栈
您可以使用位于面板顶部的标记为“按以下分组:”的下拉菜单在它们之间切换。
面板右上方还有一个标记为“筛选”的框。您可以使用它来筛选显示的快照内容,以便您可以快速查看,例如,分配了多少个特定类的对象。
类型¶
这是默认视图,看起来像这样
它将堆上的内容分组为类型,包括
JavaScript 对象:例如
Function
或Array
DOM 元素:例如
HTMLSpanElement
或Window
字符串:列为
"strings"
JavaScript 源代码:列为“
JSScript"
内部对象:例如“
js::Shape
”。它们以"js::"
为前缀。
每种类型在表中获得一行,并且行按该类型对象占用的内存量排序。例如,在上面的屏幕截图中,您可以看到 JavaScript Object
占用了大部分内存,其次是字符串。
“总计”列显示当前分配的每个类别的对象数量。
“总字节数”列显示每个类别中对象占用的字节数,以及该数字占该选项卡整个堆大小的百分比。
本节中的屏幕截图取自 怪物示例页面 的快照。
例如,在上面的屏幕截图中,您可以看到
有四个
Array
对象占总堆的 15%。
在类型名称旁边,有一个包含三个星形排列成三角形的图标
单击此图标以查看该类型的每个实例。例如,Array
的条目告诉我们快照中有四个 Array
对象。如果我们单击星形三角形,我们将看到所有四个 Array
实例
对于每个实例,您可以查看该实例的 保留大小和浅层大小。在这种情况下,您可以看到前三个数组具有相当大的浅层大小(占总堆使用量的 5%)和更大的保留大小(占总堆使用量的 26%)。
右侧是一个面板,上面写着“选择一个项目以查看其保留路径”。如果选择一个项目,您将看到该项目的 保留路径面板
调用栈¶
调用栈向您显示在代码中的哪个位置进行堆分配。
由于跟踪分配会产生运行时开销,因此必须在快照中分配内存 *之前* 通过选中“记录调用栈”来显式启用它。
然后,您将看到分配对象的每个函数的列表,按它们进行的分配的大小排序
第一条条目表示
4,832,592 字节(占总堆使用量的 93%)是在“alloc.js”第 35 行的函数中分配的,**或在该函数调用的函数中分配的**
我们可以使用展开三角形向下钻取调用树,以找到代码进行这些分配的确切位置。
使用一个简单的示例来解释这一点更容易。为此,我们将使用 DOM 分配示例。此页面运行一个脚本,该脚本创建大量 DOM 节点(200 个 HTMLDivElement
对象和 4000 个 HTMLSpanElement
对象)。
让我们获取分配跟踪
打开内存工具
选中“记录调用栈”
加载 https://mdn.github.io/performance-scenarios/dom-allocs/alloc.html
获取快照
选择“视图/聚合”
选择“按以下分组/调用栈”
您应该会看到如下内容
这告诉我们,总堆快照的 93% 是在从“alloc.js”第 35 行调用的函数中分配的(我们最初的 createToolbars()
调用)。
我们可以使用展开箭头展开树以找出我们分配内存的确切位置
这就是“字节数”和“计数值”列发挥作用的地方:它们显示了在该确切位置的分配大小和分配次数。
因此,在上面的示例中,我们可以看到我们在 createToolbarButton()
中进行了 4002 次分配,占总堆的 89%,在 alloc.js 第 9 行,位置 23:也就是说,我们创建 span 元素的确切位置。
文件名和行号是一个链接:如果我们单击它,我们将直接跳转到调试器中的该行
反向调用栈¶
调用栈视图是自上而下的:它显示在此点 **或调用树中更深层的位置** 发生的分配。因此,它非常适合获取程序内存密集型位置的概览。但是,此视图意味着您必须向下钻取很长一段时间才能找到分配发生的确切位置。
“反向调用栈”视图对此有所帮助。它提供程序的自底向上视图,显示分配发生的的确切位置,按每个位置的分配大小进行排序。然后,展开箭头将您沿着调用树向上遍历到顶层。
让我们看看当我们选择“反向调用栈”时示例是什么样子
现在在顶部,我们可以立即看到 createToolbarButton()
调用占页面堆使用量的 89%。
无可用栈¶
在上面的示例中,您会注意到堆的 7% 被标记为“(无可用栈)”。这是因为并非所有堆使用都是由您的 JavaScript 导致的。
例如
页面加载的任何脚本都占用堆空间
有时在堆栈中没有 JavaScript 时会分配对象。例如,DOM 事件对象在运行 JavaScript 和调用事件处理程序之前分配。
许多实际页面将具有比 7% 高得多的“(无可用栈)”份额。