Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 查找分离的DOM树内存泄漏_Javascript_Html_Google Chrome_Memory Leaks - Fatal编程技术网

Javascript 查找分离的DOM树内存泄漏

Javascript 查找分离的DOM树内存泄漏,javascript,html,google-chrome,memory-leaks,Javascript,Html,Google Chrome,Memory Leaks,我在诊断一个非常大的单页web应用程序中分离的DOM树内存泄漏时遇到了问题,该应用程序主要是用Knockout构建的 我已经调整了应用程序,将一个伪FooBar对象附加到一个特定的HTML按钮元素,当用户移动到应用程序的不同页面时,该元素应该被垃圾收集。使用Chrome的heap snapshot函数,我可以看到一个应该被GC’ed的旧FooBar实例仍然可以从一个大的分离DOM树中的HtmlButtoneElement访问 通过保留树面板跟踪引用,我沿着从GC根开始逐渐缩短的距离的链进行跟踪。

我在诊断一个非常大的单页web应用程序中分离的DOM树内存泄漏时遇到了问题,该应用程序主要是用Knockout构建的

我已经调整了应用程序,将一个伪FooBar对象附加到一个特定的HTML按钮元素,当用户移动到应用程序的不同页面时,该元素应该被垃圾收集。使用Chrome的heap snapshot函数,我可以看到一个应该被GC’ed的旧FooBar实例仍然可以从一个大的分离DOM树中的HtmlButtoneElement访问

通过保留树面板跟踪引用,我沿着从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应用程序代码中令人不快的部分——但这让我很为难

首先-不要将删除作为建议的注释之一。将引用设置为null是正确的处理方法。delete将断开隐藏的类。要亲自查看,请运行以下示例:

Rafe,你在profiler中看到的内容通常很难理解。你在这里发布的信息看起来很奇怪,可能是一个bug或是应用程序浏览器之外的内存泄漏,但如果不运行你的应用程序,很难判断。您的保留树在函数的上下文中结束,可以通过引用该函数或共享该上下文的其他函数来保留它。它可能太复杂,探查器无法正确地将其可视化

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

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

如果您需要更多详细信息,可以在探查器中拍摄多个快照,这样您就可以在使用时间线找到泄漏原因之前和之后创建一个快照—您现在知道导致泄漏的确切操作。然后,您可以在探查器中比较这些内容-这里有一个比较视图。这比其他人更容易理解

您还可以从探查器中保存堆快照并将其发布到在线,以便我们可以查看。在左边的列表中,它们每个都有一个保存链接

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

但真正完整的内存分析器使用指南如下:


更新链接:

你能分享一些代码吗,特别是这个元素是在哪里创建的,在哪里处置的?我担心代码是专有的,而且非常庞大;我还没有机会试着在小型计算机上复制它。这里真正的问题是,为什么Chrome堆探查器应该报告上面这样的内容,而不是从根开始,这是怎么回事?!。您必须使用delete删除属性foobar;删除button.foobar,然后再删除DOM元素,并确保没有剩余的事件侦听器。我认为这不是一个bug。目前,我正在开发一个巨大的SPA,使用我自己的框架与DOJO相结合。内存泄漏也是一个大问题。创建的内存泄漏最多,因为我没有适当地销毁connectionsevent侦听器,并且引用了其他objectsouter范围。将“普通”对象更改为模块模式后,我的泄漏消失了。总结;你能把代码贴出来吗?你是如何用foobar属性创建按钮的?@Rafe但是我们该如何帮助你呢?解决方案已经给出:您仍然有对对象的引用。GC正在计算对对象的剩余引用。如果它变为0,则对象将被垃圾收集。否则,当可能再次调用对象时,将始终存在引用。内存泄漏有很多种:闭包、循环引用。。如果没有提供代码,我们只能解释理论。早些时候,我曾试图解决1GB JS上的内存泄漏问题,非常感谢!我们现在很忙,但我一有空下午就试试你的建议。很高兴看到有人同意我的观点
跟踪看起来很奇怪。突出显示为黄色的节点直接引用JavaScript代码。高亮显示为红色的节点没有直接引用。它们之所以活着,是因为它们是黄色节点树的一部分。通常,您希望将重点放在黄色节点上。修复您的代码,使黄色节点的活动时间不会超过需要的时间,并且您还可以删除黄色节点树中的红色节点。但是如果您只有红色节点呢?@Legends。我在节点计数方面也有一些问题,只有红色突出显示的分离节点。