使用分离元素工具调试 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 分离元素工具调试内存泄漏
使用分离元素工具修复内存泄漏的策略
- 打开要分析的网页。
- 打开 “分离元素” 工具。
- 运行垃圾回收,删除 JavaScript 对象不再引用的所有节点。
- 获取所有无法进行垃圾回收的分离元素。
- 分析特定的分离元素及其 JavaScript,以识别导致保留整个树的分离树中的罪魁祸首节点。
获取分离的元素并分析分离元素的 JavaScript
使用分离元素演示网页分析 分离元素 :
在新窗口或选项卡中打开 “分离元素”演示网页 。
最初选择了 “会议室 1 ”按钮。 在演示网页的 JavaScript 代码中,类的
Room
实例用于管理会议室 1 中的消息。右键单击网页,然后选择“ 检查”。 或者,按 Ctrl+Shift+I(Windows、Linux)或 Command+Option+I (macOS)。
DevTools 随即打开。
在 DevTools 的 “活动栏”中,选择“ 分离元素 ” () 选项卡。如果该选项卡不可见,请单击“ 更多工具 () 按钮,或扩大 DevTools。 此时会打开 “分离元素” 工具:
生成将由 Room 类的 JavaScript 实例存储的消息:
在演示网页中,单击“ 快速流量 ”按钮。
演示网页开始生成消息并将其显示在网页中:
显示某些消息后,单击演示网页中的 “停止 ”按钮。
每条消息都是
<div class="message">
类的 Room 1 实例引用的Room
元素。 网页 DOM 树中没有分离的元素,因为所有消息元素都附加到 Room 类的当前 Room 1 实例。更改为 Room 类的不同实例,使元素分离:
在演示网页中,单击“ 会议室 2 ”按钮,该按钮对应于类的另一个实例
Room
。在网页中,消息消失:
为 Room 类的 Room 1 实例生成的消息 (
<div class="message">
元素) 不再附加到 DOM,但仍由 Room 类的 Room 1 实例引用。 它们是分离的元素,这可能会导致内存泄漏,除非网页将再次使用这些元素。获取分离元素的列表:
在 DevTools 的 “分离元素” 工具中,单击“ 回收垃圾 ” () 图标。
浏览器运行垃圾回收,删除 JavaScript 对象不再引用的任何节点。
在 “分离元素 ”工具中,单击“ 获取分离元素 ” () 按钮。
将显示无法进行垃圾回收的分离 DOM 元素:
如果应用程序不会重复使用这些分离的元素,则它们是内存泄漏。
标识引用特定分离元素的 JavaScript 代码:
在 “分离元素 ”工具中,单击“ 分析 ” () 按钮。
“分离元素”工具底部会短暂显示一条消息,即“获取内存堆快照...”,然后显示消息“全部完成”。 内存工具在 DevTools 底部的“快速视图”面板中打开:
如果 “分析类型 ”选项按钮显示在 “内存 ”工具中,而不是 “摘要 ”和“ 保留项 ”UI 中,请再次单击“ 分析 ” (“ ) 按钮。
在 “分离元素” 工具的“ ID ”列中,双击 ID,例如 @21299 或 @21783。
这是内存堆快照中的一个元素的唯一
<div class="message">
标识符。 内存工具在“保留器”选项卡中显示保留器:内存工具会自动选择堆中引用分离元素的对象。 此类对象称为 保留器。
在“ 保留器 ”选项卡中,在有关成员的
unmounted
保留器子条目(例如 在会议室 @54011 中卸载)中,单击 链接room.js:13。源工具将在活动栏中打开,并显示第 13 行文件 room.js (
Room
构造函数) :unmounted
是 类的Room
数组成员,在构造函数的第 19 行中定义:this.unmounted = [];
。向下滚动到 类的 方法
Room
中的hide
第 49this.unmounted.push(el);
行:代码将房间中的每个消息添加到
unmounted
数组。 数组unmounted
是引用分离元素的对象。
在 JavaScript 代码中,你现在已 (数组) 标识了保留器对象 unmounted
,防止浏览器对分离的元素进行垃圾回收。
你已找到浏览器无法垃圾回收的分离元素,并找到了仍在引用分离元素的 JavaScript 对象。 然后,可以更改 JavaScript 代码以释放元素,以减少网页上分离的元素数,从而提高网页性能和响应能力。
标识导致其他 DOM 节点保留的 DOM 节点
由于 DOM 是一个完全连接的图形,因此当 JavaScript 将一个 DOM 节点保留在内存中时,它可能会导致其他 DOM 节点随它一起保留。
若要识别导致保留整个树的分离树中的罪魁祸首节点,请执行以下操作:
单击“ 分离元素 ” () 图标可销毁分离树中的父子链接。
单击“ 回收垃圾 () 图标。
父子链接在分离树中删除,其余项是 DOM 节点,该节点导致其他 DOM 节点被保留:
将所选目标更改为其他源
若要使用“所选目标”下拉列表为来自不同源或帧的分离元素检查:
单击 “所选目标 ”下拉列表:
选择其他源。
新原点显示在 “分离元素” 工具中。
关于分离的元素和内存泄漏
分离元素并不总是内存泄漏的指示,内存泄漏并不总是由分离元素引起的。 内存泄漏取决于应用程序的上下文。
当元素不再附加到文档对象模型 (DOM) 树,但仍被网页上运行的某些 JavaScript 引用时,应用程序中可能会出现内存泄漏。 这些元素称为 分离元素。 要使浏览器对分离元素 (GC 进行垃圾回收) ,不得从 DOM 树或 JavaScript 代码引用该元素。
内存问题会影响网页性能,包括内存泄漏、内存膨胀和频繁的垃圾回收。 用户的症状包括:
- 随着时间推移,网页的性能会逐渐恶化。
- 网页的性能一直很差。
- 网页的性能延迟或似乎经常暂停。
在获取分离的元素之前运行 GC,以便仅显示不能为 GC 的元素
若要仅显示从 DOM 树分离且无法进行垃圾回收的元素,请始终先单击“ 回收垃圾 ”,然后单击“ 获取分离的元素”。
尽管某些元素在某个时间点可能显示为分离,但在运行 GC 之前,你不会知道网页中的 JavaScript 代码是否仍实际引用它们。 在演示应用中在聊天室之间切换时,网页会删除用于显示 DOM 消息的元素。 但是切换到 类的不同实例 Room
不会完全删除这些元素,并且对这些元素的引用仍然存在,因此,这些元素会保留在内存中。
重新附加元素
对于分离元素演示网页,有必要保留聊天消息列表,以便在用户切换回 会议室 1 时保留消息日志。 同样,当用户滚动经过元素时,社交媒体中的源可能会分离元素,并在用户向上滚动时将其重新附加到 DOM。
当 分离元素 工具报告分离元素时,不一定是内存泄漏。 由你决定什么是内存泄漏,什么不是。 也许你的应用会在稍后 (重新附加这些元素,而不必重新创建它们,这可能) 较慢。
分离 DOM 节点是一种有用的方法,只要最终重用这些分离的元素 (或删除它们) 。 分离元素工具的值是,当你怀疑内存泄漏时,可以检查该工具是否报告了越来越多的意外分离 DOM 元素。
长时间运行的应用和卸载组件
请务必卸载组件。 对于长时间运行的应用,仅几 KB 的小内存泄漏会随着时间的推移明显降低性能。 对于使用 React 框架的网页,React维护 DOM 的虚拟化副本。 未能正确卸载组件可能会导致应用程序泄漏虚拟 DOM 的大部分内容。
报告问题
如果发现 分离元素 功能的工作原理有问题, 请联系 Microsoft Edge DevTools 团队 ,发送有关 分离元素 功能和内存泄漏调试的反馈。
另请参阅
- 修复内存问题中的用于调查分离元素的工具 - 查看分离元素的工具比较。
演示:
- 分离元素演示网页
- MicrosoftEdge/Demos > 分离元素 存储库文件夹 - 源代码。