使用分离元素工具调试 DOM 内存泄漏

使用 分离元素 工具查找浏览器无法垃圾回收的分离元素,并找到仍在引用分离元素的 JavaScript 对象。 通过更改 JavaScript 以释放 元素,可以减少页面上分离的元素数。

当元素不再附加到文档对象模型 (DOM) 树,但仍被页面上运行的某些 JavaScript 引用时,应用程序中可能会出现内存泄漏。 这些元素称为 分离元素。 要使浏览器对分离元素 (GC 进行垃圾回收) ,不得从 DOM 树或 JavaScript 代码引用该元素。

有关堆快照和分离元素的详细信息,请阅读 使用堆快照发现分离的 DOM 树内存泄漏

修复内存问题中所述,内存问题会影响页面性能,包括内存泄漏、内存膨胀和频繁的垃圾回收。 用户的症状包括:

  • 随着时间的推移,页面的性能会逐渐恶化。
  • 页面的性能一直很差。
  • 页面的性能延迟或似乎经常暂停。

打开分离元素工具

若要打开 “分离元素” 工具并加载演示页,请执行以下操作:

  1. 在新窗口或选项卡中打开 “分离元素”演示应用程序

  2. 若要打开 DevTools,请右键单击网页,然后选择“ 检查”。 或者,按 Ctrl+Shift+I (Windows、Linux) 或 Command+Option+I (macOS) 。 DevTools 随即打开。

  3. 在 DevTools 的 “活动栏”中,选择“ 分离元素 ”选项卡。如果该选项卡不可见,请单击“ 更多工具 (更多工具”图标) 按钮:

    打开分离元素工具

获取分离的元素

获取分离元素 ” (“ 分离元素”工具 中的“获取 分离元素 ”图标) 按钮可查找并显示网页上的所有分离元素。

若要查找分离的元素,请执行:

  1. 在演示应用程序中,确保已选择 “会议室 1 ”按钮。

  2. 在演示应用程序中,单击“ 快速流量 ”按钮。

  3. 生成并在演示应用程序中显示某些消息后,单击演示的 “停止 ”按钮:

    在演示应用程序中生成一些消息

  4. 单击会议室 2 按钮:

  5. “分离元素 ”工具中,单击“ 获取分离元素 ” (“获取分离元素”图标) 图标。

    分离元素” 工具显示页面的所有分离元素。 在演示应用程序中切换到 会议室 2 时, 会议室 1 中生成的消息不再附加到 DOM,但仍由 JavaScript 引用:

    使用分离元素工具获取分离元素

触发垃圾回收

接下来,在浏览器中触发垃圾回收 (GC) :

  1. “分离元素” 工具中,单击“ 回收垃圾 ” (“回收垃圾”图标) 图标。

  2. 单击“ 获取分离元素 ” (“获取分离元素”图标) 图标。

选择“ 回收垃圾”时,浏览器将运行垃圾回收。 选择“ 获取分离元素”时,“ 分离元素” 工具将显示无法进行垃圾回收的所有分离元素。 如果应用程序不重复使用这些分离的元素,则可能是内存泄漏。

标识保留分离元素的 JavaScript 代码

找到无法进行垃圾回收的分离元素后,可以使用“分离元素”工具中的“分析 (”分析“图标) 按钮来标识仍在引用分离元素的页面上运行的 JavaScript 代码。 “分析”按钮获取堆快照,并使用其在堆中的位置填充分离元素的 ID

有关堆快照的详细信息,请阅读 使用内存工具记录堆快照

标识引用分离元素的 JavaScript 代码:

  1. “分离元素 ”工具中,单击“ 分析 ” (“分析”图标) 图标。

    “内存”工具将在 DevTools 底部的“快速视图”工具栏中打开:

    分析分离元素工具中的分离元素

  2. 从“ 分离元素 ”工具中,选择分离元素的 “ID” 字段。

    内存工具会自动选择堆中引用分离元素的对象。 我们称这些对象 为 Retainers

    从分离元素工具引用堆快照

  3. “内存 ”工具中,选择 链接room.js:13

    工具将在活动栏中打开,并显示文件的第 13 行 room.js

  4. hide()room.js函数中,演示应用程序的 JavaScript 代码将房间中的每个消息添加到数组unmounted中。 数组 unmounted 是引用分离元素的对象:

    标识保留分离元素的 JavaScript

现在,你已确定阻止浏览器对分离的元素进行垃圾回收的保留器!

标识导致其他节点被保留的 DOM 节点

由于 DOM 是一个完全连接的图形,因此当 JavaScript 将一个 DOM 节点保留在内存中时,它可能会导致其他 DOM 节点随它一起保留。

若要识别导致保留整个树的分离树中的罪魁祸首节点,请执行以下操作:

  1. 单击“ 分离元素 ” (“分离元素”图标) 图标可销毁分离树中的父子链接。

  2. 单击“ 回收垃圾 (”回收垃圾“图标) 图标。

    在分离树中删除父子链接:

    分离元素工具中的“分离元素”按钮

将所选目标更改为其他源

可以使用“所选目标”下拉列表为来自不同源或帧的分离元素检查。

  1. 单击 “所选目标 ”下拉列表:

    “所选目标”下拉列表允许你选择不同的源

  2. 选择其他源。

新原点显示在 “分离元素” 工具中。

其他注意事项

查找内存泄漏时,请记住,泄漏可能取决于应用程序的上下文。 对于演示应用程序,你发现了浏览器无法进行垃圾回收的分离元素,并标识了保留分离元素的 JavaScript。 但是,在演示应用程序的上下文中,保留聊天消息列表是有意义的,这样,如果用户切换回 会议室 1,则保留消息日志。

下图显示了当用户从 会议室 2 导航回会议室 1 时重新附加的消息形式的分离元素:

切换回会议室 1 时,分离的元素会重新附加到 DOM

同样,当用户滚动经过元素时,社交媒体中的源可能会分离元素,并在用户向上滚动时将其重新附加到 DOM。 分离元素并不总是内存泄漏的指示,内存泄漏并不总是由分离元素引起的。

对于长时间运行的应用,仅几 KB 的小内存泄漏会随着时间的推移明显降低性能。 使用 React 框架的 Web 开发人员知道,React维护 DOM 的虚拟化副本。 未能正确卸载组件可能会导致应用程序泄漏虚拟 DOM 的大部分内容。

此演示应用及其泄漏是人为的。 在生产网站或应用上测试分离元素工具。 如果发现分离元素工具存在潜在问题, 请联系 Microsoft Edge DevTools 团队 ,发送有关 分离元素 工具和内存泄漏调试的反馈。