javascript - 定位分离的 DOM 树内存泄漏

标签 javascript html google-chrome memory-leaks

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

我调整了应用程序,将虚拟 FooBar 对象附加到特定的 HTML 按钮元素,当用户移动到应用程序的不同“页面”时,该元素应该被垃圾收集。使用 Chrome 的 heap snapshot 功能,我可以看到旧的 FooBar 实例(应该已经被 GC 处理过)仍然可以从它的 HTMLButtonElement 访问在(大)分离的 DOM 树中。

通过保留树 面板跟踪引用,我沿着链从 GC 根开始递减的距离。但是,在某个时刻,我的搜索在距根节点距离为 4 的节点处到达了死胡同(在本例中)!保留树报告根本没有对此节点的引用,但不知何故知道它距离 GC 根有四步。

下面是retaining tree让我疑惑的部分(右边的数字是到根的距离):

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 中的示例

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

不过,我可以帮助您查明问题。

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

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

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


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

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

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

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

关于javascript - 定位分离的 DOM 树内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21226646/

相关文章:

javascript - 如何从google maps api获取国家?

javascript - 如何使用相同的 HTML 通过不同的 url 呈现不同的内容?

javascript - Koa v2,在passport-loca登录后获取用户对象

javascript - 如何隐藏 li 中值小于输入数字的元素

javascript - Chrome MJPEG CORS "invalid response"当 img.crossOrigin ="Anonymous"

javascript - Videojs-contrib-hls 在 safari 上返回未定义

jquery - 嵌套元素的悬停功能

javascript - 如何使用 JavaScript 查找 HTML 页面中的空格?

javascript - 将 WebExtension 从 Chrome 移植到 Firefox?

javascript - Chrome 插件 Dropbox 集成