定位分离的 DOM 树内存泄漏

2024-05-02

我在诊断主要使用 Knockout 构建的非常大的单页 Web 应用程序中的分离 DOM 树内存泄漏时遇到问题。

我已经调整了应用程序以附加一个假人FooBar对象特定的 HTML 按钮元素,当用户移动到应用程序的不同“页面”时,该元素应该被垃圾收集。使用 Chrome 的堆快照函数,我可以看到一个旧的FooBar实例(应该已被 GC 处理)仍然可以从其访问HTMLButtonElement在(大的)分离的 DOM 树中。

通过追踪参考文献挡土树面板中,我沿着与 GC 根的距离逐渐减小的链。然而,在某个时刻,我的搜索在距根节点距离 4 的节点处到达了死胡同(在这种情况下)!保留树根本没有报告对此节点的引用,但不知何故知道它距离 GC 根有四个步骤。

这是保留树中让我困惑的部分(右侧的数字是距根的距离):

v foobar in HTMLButtonElement                                  10
  v [4928] in Detached DOM tree / 5643 entries                  9
    v native in HTMLOptionElement                               8
      v [0] in Array                                            7
        v mappedNodes                                           6
          v [870] in Array                                      5
            v itemsToProcess in system / Context                4
                context in function itemMovedOrRetained()
                context in function callCallback()

保留树不显示此处距离 3 或以上的引用。

谁能向我解释一下吗?我希望能够沿着参考链回到 JavaScript 应用程序代码的有问题的部分——但这让我陷入了困境!


首先 - 不要使用delete正如评论之一所建议的那样。设置参考null是处理东西的正确方法。delete打破“隐阶级”。要亲自查看,请运行我的示例https://github.com/naugtur/js-memory-demo https://github.com/naugtur/js-memory-demo

Rafe,你在分析器中看到的内容通常很难理解。您在此处发布的内容确实看起来很奇怪,可能是应用程序外部的错误或内存泄漏(浏览器也泄漏),但如果不运行您的应用程序,就很难判断。您的保留树以函数的上下文结束,并且可以通过对该函数或共享上下文的其他函数的引用来保留它。对于分析器来说,它可能太复杂而无法正确可视化。

不过我可以帮助你找出问题所在。

首先,转到开发工具中的“时间轴”选项卡并使用它来观察泄漏发生的时刻。仅选择内存分配并开始录制。经历一个您预计会泄漏的场景。保持蓝色的条是泄漏。您可以在时间轴中选择它们的周围并关注它们的保留树。独立 dom 树中最有趣的元素是红色元素 - 它们是从外部引用的。其余部分被保留,因为树中的任何元素被引用,它都引用了其他所有元素(x.parentNode)

如果您需要更多详细信息,您可以在分析器中拍摄多个快照,以便您在泄漏原因之前和之后都有一个快照(您通过时间线找到的 - 您现在知道导致泄漏的确切操作)。然后,您可以在探查器中比较它们 - 有一个“比较”视图。这比其他人更容易理解。

您还可以从分析器中保存堆快照并将其发布到网上,以便我们查看。左侧列表中的每个项目都有一个保存链接。


分析内存很困难,实际上需要一些练习和对工具的理解。 你可以练习我演讲中的一些例子:

http://naugtur.pl/pres/mem.html#/5/2 http://naugtur.pl/pres/mem.html#/5/2

但使用内存分析器的真正完整指南是这个文档:

https://developer.chrome.com/devtools/docs/javascript-memory-profiling#looking_up_color_coding https://developer.chrome.com/devtools/docs/javascript-memory-profiling#looking_up_color_coding

更新的链接: https://developers.google.com/web/tools/profile-performance/memory-problems/memory-diagnosis https://developers.google.com/web/tools/profile-performance/memory-problems/memory-diagnosis

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

定位分离的 DOM 树内存泄漏 的相关文章

随机推荐

  • 帮助我在 Python 中实现反向传播

    EDIT2 新的训练集 Inputs 0 0 0 0 0 0 1 0 0 0 2 0 0 0 3 0 0 0 4 0 1 0 0 0 1 0 1 0 1 0 2 0 1 0 3 0 1 0 4 0 2 0 0 0 2 0 1 0 2 0 2
  • 如何以编程方式移动 OpenLayers Vector?

    API 文档为OpenLayers Feature Vector http dev openlayers org apidocs files OpenLayers Feature Vector js html说 Vector 本身根本没有方
  • C# 数据库包装设计

    我正在为 C 设计一个数据库包装器 以下是我有两个选择 选项A class DBWrapper IDisposable private SqlConnection sqlConn public DBWrapper sqlConn new S
  • 将自定义字段添加到 Django 中的 auth_user 表

    目前我创建了另一个类 表名为MyAppUser我的自定义列 例如地址和电话号码 具有 Django 身份验证的外键User 像这样的东西 from django db import models from django contrib au
  • 使用 SvelteKit 托管 Firebase

    我已经创建了一个 svelte 应用程序并使用 SvelteKit 构建应用程序 一切正常 我尝试在 firebase 托管中部署此应用程序 但失败了 Sveltekit 生成生产版本 svelte kit文件夹 我试图改变public对象
  • Android Google Maps API OnLocationChanged 仅调用一次

    每当我的位置发生变化时 我都会尝试更新我的相机 然而 onLocationChanged 只被调用一次 当我随后在模拟器中发送新位置时 不会调用 onLocationChanged 我已经尝试了几个小时了 但似乎无法修复它 public c
  • 提高UDP可靠性

    我正在构建一个基于 UDP 的小型服务器 服务器基于 Net并使用它自己的Socket类 我通过 ReceiveMessageFromAsync 和异步发送使用完成端口 我的问题是我失去了大约 5 10 的流量 现在我明白这是正常的 但是有
  • 自己应用程序锁屏中的 iPod 控制

    如何为我自己的应用程序使用锁屏 iPod 控件 我尝试了MPNowPlayingInfoCenter 但是如果我设置了信息 它就不会显示在任何地方 不在锁定屏幕上 也不在 AppleTV 上播放 我使用 AVPlayer 来播放我的音频文件
  • Sonarqube C# 扫描仪异常:“java.lang.IllegalArgumentException:不是指针的有效行偏移量”

    有谁知道这是怎么回事 在Windows服务器上使用Sonarqube v5 6 c 扫描仪v5 5 0 479 似乎是在多个文件中发现这一点 而不总是相同的文件 这是最令人担忧的 有人有主意吗 16 46 03 INFO Importing
  • 使用 MOVE 确定 DB RESTORE 的 SQL 数据路径

    我正在尝试编写一个自动恢复数据库备份的脚本 我知道我可以使用以下 RESTORE 命令 RESTORE DATABASE DBRestoredName FROM DISK N C path to backup bak WITH FILE 1
  • Python 中的“lambda”是什么意思,最简单的使用方法是什么?

    您能否给出一个示例和其他示例来说明何时以及何时不使用 Lambda 我的书给了我一些例子 但它们很令人困惑 拉姆达 起源于拉姆达演算 http en wikipedia org wiki Lambda calculus和 AFAIK 首先实
  • 使用实体框架而不使用 using 语句的缺点?

    有很多这样的代码块 public class SomeController Controller DbEntities entity new DbEntities public ActionResult Add entity someOpe
  • 使用accumulate计算数组double[]平均值的函数

    它一定是最常见的函数 每个人在某处都有代码片段 但我实际上花了不少于 1 5 小时在 SO 以及其他 C 网站上搜索它 但还没有找到解决方案 我想计算 a 的平均值double array 使用函数 我想将数组作为函数传递给参考 有数百万个
  • 使用node和multer将图像上传到heroku不起作用

    我正在尝试使用 Node 后端将图像文件上传到 Heroku 我可以使其工作 同样的过程在本地主机测试中工作得很好 但是在将我的项目部署到 Heroku 并测试它之后 过程和文件中出现错误不会上传 后端 let storage multer
  • python字符串包含双引号字符

    我的输入字符串由字符组成 包括双引号和单引号 和 B SS JU PQ AD DDSFD ABD E J 但是 当我从文本文件打开上述输入并打印它时 第三行中的双引号 被打印为 xe2 x80 x9d 我的目标是进行简单的字符计数 B 2
  • 如何避免在 Excel 中垂直合并单元格?

    我厌倦了合并单元格 它们就是行不通 因此 当我只需要文本在多列中居中时 我找到了一种避免水平合并单元格的方法 那是 Range A1 C1 HorizontalAlignment xlCenterAcrossSelection 它就像一个魅
  • MvxListView 可检查列表项

    我想让 CustomChoiceList 与 MvvmCross 一起使用 但很难让示例正常工作 ListItem 不会被选中 事实上 该示例使用自定义 LinearLayout 来扩展 LinearLayout 并实现 ICheckabl
  • tf.data.Dataset 迭代器返回 Tensor("IteratorGetNext:1", shape=(None, 16), dtype=int32) 但无法获取张量的值

    我正在尝试编写一个自定义模型 其中我正在编写一个自定义train step功能 我正在从自定义数据生成器创建 tf data Dataset 例如 tds tf data Dataset from generator tdg iter ar
  • 如何加速Python循环

    我查看了几个网站上的一些讨论 但没有一个给我解决方案 这段代码运行时间超过5秒 for i in xrange 100000000 pass 我正在研究整数优化问题 我必须使用O n log n 算法编辑 O n 4 算法 其中n代表矩阵的
  • 定位分离的 DOM 树内存泄漏

    我在诊断主要使用 Knockout 构建的非常大的单页 Web 应用程序中的分离 DOM 树内存泄漏时遇到问题 我已经调整了应用程序以附加一个假人FooBar对象特定的 HTML 按钮元素 当用户移动到应用程序的不同 页面 时 该元素应该被