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

分离 元素 工具是一种在网页上查找和显示所有分离元素的方法。 有关评估内存泄漏的其他方法,请参阅修复内存问题中的用于调查分离元素的工具

重要

已弃用 分离元素 工具。 从 Microsoft Edge 130 开始, 分离元素 工具会显示一条消息,指出该工具已弃用;相反,在 内存 工具的初始 “选择分析类型” 屏幕中,选择“ 分离元素 ”选项按钮。 仅限 Edge 的 Chrome DevTools 协议 (CDP) 函数 EdgeDOMMemory.getDetachedNodesIds 可继续工作,但改用 DOM.getDetachedDomNodes

在 Microsoft Edge 133 中,将删除 分离元素 工具;相反,在 内存 工具的初始 “选择分析类型” 屏幕中,选择“ 分离元素 ”选项按钮。 CDP 函数 EdgeDOMMemory.getDetachedNodesIds 将被删除;请改用 DOM.getDetachedDomNodes

若要提高网页的性能,请找到与 DOM 树分离的元素,并且你不希望这些元素仍会被 JavaScript 代码引用。 查找浏览器无法垃圾回收的分离元素,因为代码仍引用它们,然后释放对分离元素的 JavaScript 代码引用。

“分离元素”工具,其中显示了分离元素的列表

分离元素工具,显示内存工具中的保留符,以及用于在工具中打开 JavaScript 代码的链接:

分离元素工具,显示保留符

视频:使用 Microsoft Edge 分离元素工具调试内存泄漏

视频“使用Microsoft边缘分离元素工具调试内存泄漏”的缩略图

使用分离元素工具修复内存泄漏的策略

  1. 打开要分析的网页。
  2. 打开 “分离元素” 工具。
  3. 运行垃圾回收,删除 JavaScript 对象不再引用的所有节点。
  4. 获取所有无法进行垃圾回收的分离元素。
  5. 分析特定的分离元素及其 JavaScript,以识别导致保留整个树的分离树中的罪魁祸首节点。

获取分离的元素并分析分离元素的 JavaScript

使用分离元素演示网页分析 分离元素

  1. 在新窗口或选项卡中打开 “分离元素”演示网页

    最初选择了 “会议室 1 ”按钮。 在演示网页的 JavaScript 代码中,类的 Room 实例用于管理会议室 1 中的消息。

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

    DevTools 随即打开。

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

    打开分离元素工具

    生成将由 Room 类的 JavaScript 实例存储的消息:

  4. 在演示网页中,单击“ 快速流量 ”按钮。

    演示网页开始生成消息并将其显示在网页中:

    在演示网页中生成一些消息

  5. 显示某些消息后,单击演示网页中的 “停止 ”按钮。

    每条消息都是 <div class="message"> 类的 Room 1 实例引用的 Room 元素。 网页 DOM 树中没有分离的元素,因为所有消息元素都附加到 Room 类的当前 Room 1 实例。

    更改为 Room 类的不同实例,使元素分离:

  6. 在演示网页中,单击“ 会议室 2 ”按钮,该按钮对应于类的另一个实例 Room

    在网页中,消息消失:

    会议室 2 初始视图

    Room 类的 Room 1 实例生成的消息 (<div class="message"> 元素) 不再附加到 DOM,但仍由 Room 类的 Room 1 实例引用。 它们是分离的元素,这可能会导致内存泄漏,除非网页将再次使用这些元素。

    获取分离元素的列表:

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

    浏览器运行垃圾回收,删除 JavaScript 对象不再引用的任何节点。

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

    将显示无法进行垃圾回收的分离 DOM 元素:

    “获取分离的元素”按钮

    如果应用程序不会重复使用这些分离的元素,则它们是内存泄漏。

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

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

    分离元素”工具底部会短暂显示一条消息,即“获取内存堆快照...”,然后显示消息“全部完成”。 内存工具在 DevTools 底部的“快速视图”面板中打开:

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

    如果 “分析类型 ”选项按钮显示在 “内存 ”工具中,而不是 “摘要 ”和“ 保留项 ”UI 中,请再次单击“ 分析 ” (“ 分析”图标) 按钮。

  10. “分离元素” 工具的“ ID ”列中,双击 ID,例如 @21299@21783

    这是内存堆快照中的一个元素的唯一<div class="message">标识符。 内存工具在“保留器”选项卡中显示保留器

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

    内存工具会自动选择堆中引用分离元素的对象。 此类对象称为 保留器

  11. 在“ 保留器 ”选项卡中,在有关成员的 unmounted 保留器子条目(例如 在会议室 @54011 中卸载)中,单击 链接room.js:13

    工具将在活动栏中打开,并显示第 13 行文件 room.js (Room 构造函数) :

    room.js 中的第 13 行:Room 构造函数

    unmounted 是 类的 Room 数组成员,在构造函数的第 19 行中定义: this.unmounted = [];

  12. 向下滚动到 类的 方法Room中的 hide 第 49 this.unmounted.push(el); 行:

    标识保留分离元素的 JavaScript

    代码将房间中的每个消息添加到 unmounted 数组。 数组 unmounted 是引用分离元素的对象。

在 JavaScript 代码中,你现在已 (数组) 标识了保留器对象 unmounted ,防止浏览器对分离的元素进行垃圾回收。

你已找到浏览器无法垃圾回收的分离元素,并找到了仍在引用分离元素的 JavaScript 对象。 然后,可以更改 JavaScript 代码以释放元素,以减少网页上分离的元素数,从而提高网页性能和响应能力。

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

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

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

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

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

    父子链接在分离树中删除,其余项是 DOM 节点,该节点导致其他 DOM 节点被保留:

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

将所选目标更改为其他源

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

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

    使用“所选目标”下拉列表选择不同的源

  2. 选择其他源。

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

关于分离的元素和内存泄漏

分离元素并不总是内存泄漏的指示,内存泄漏并不总是由分离元素引起的。 内存泄漏取决于应用程序的上下文。

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

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

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

在获取分离的元素之前运行 GC,以便仅显示不能为 GC 的元素

若要仅显示从 DOM 树分离且无法进行垃圾回收的元素,请始终先单击“ 回收垃圾 ”,然后单击“ 获取分离的元素”。

尽管某些元素在某个时间点可能显示为分离,但在运行 GC 之前,你不会知道网页中的 JavaScript 代码是否仍实际引用它们。 在演示应用中在聊天室之间切换时,网页会删除用于显示 DOM 消息的元素。 但是切换到 类的不同实例 Room 不会完全删除这些元素,并且对这些元素的引用仍然存在,因此,这些元素会保留在内存中。

重新附加元素

对于分离元素演示网页,有必要保留聊天消息列表,以便在用户切换回 会议室 1 时保留消息日志。 同样,当用户滚动经过元素时,社交媒体中的源可能会分离元素,并在用户向上滚动时将其重新附加到 DOM。

分离元素 工具报告分离元素时,不一定是内存泄漏。 由你决定什么是内存泄漏,什么不是。 也许你的应用会在稍后 (重新附加这些元素,而不必重新创建它们,这可能) 较慢。

分离 DOM 节点是一种有用的方法,只要最终重用这些分离的元素 (或删除它们) 。 分离元素工具的值是,当你怀疑内存泄漏时,可以检查该工具是否报告了越来越多的意外分离 DOM 元素。

长时间运行的应用和卸载组件

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

报告问题

如果发现 分离元素 功能的工作原理有问题, 请联系 Microsoft Edge DevTools 团队 ,发送有关 分离元素 功能和内存泄漏调试的反馈。

另请参阅

演示: