【问题标题】:Memory leaks with closures and (jQuery) DOM events in current browsers?当前浏览器中的闭包和 (jQuery) DOM 事件导致内存泄漏?
【发布时间】:2012-01-14 12:47:44
【问题描述】:

我是 javascript 新手,似乎在跟踪内存泄漏时遇到了一些问题。我已将其缩小到似乎会导致内存泄漏的部分,因为代码相当复杂。我将发布一个不同的示例,将其简单化但会导致相同的问题(只是小得多)。

Code Example

基本上,我有一些代码可以动态构建 HTML 并将事件附加到 HTML。每次 AJAX 请求都会重建 HTML。这一切都在第一次工作得很好,但是在每次 AJAX 请求之后,浏览器内存都会增加(并不总是相等)!通过在 jsfiddle 上多次单击运行并查看浏览器内存可以重现此问题。我的假设是创建的闭包永远不会被垃圾收集,但我不确定?如果是这种情况,有没有更好的方法来做到这一点而不会导致任何问题的闭包?

这发生在 FF8、最新版本的 Chrome 和 IE 8 中。很可能所有其他版本 - 正是我测试过的。

我在代码中添加了一些 cmets,应该会有所帮助。

谢谢!

编辑: 好的,所以在使用 sIEve 进行更多研究之后,我可以看到每次 AJAX 调用时 DOM 节点的数量增加了一倍。我已经更新了示例来模拟这一点。所以我的问题是为什么在调用 jQuery 为空或删除函数后 DOM 元素没有被垃圾收集?我还遍历了取消绑定事件处理程序的东西中的元素,并将每个 DOM 元素 js 引用设置为 null 而没有影响...

Code Example

【问题讨论】:

  • IE6 存在一些 HTML/DOM-JS 内存问题等(问题是 DOM 有一个内存模型,而 JS 引擎有另一个并试图在两者之间解决),尽管我认为这在很大程度上已经解决了......不确定现代浏览器中是否存在任何当前的“陷阱”。
  • 我无法在最新的 Chrome 上重现这个:/
  • 可能想说 Chrome 的“最新版本”是什么,因为它并不总是相同的。此外,指定使用的 jQuery 版本。 :) Old versions of jQuery had a memory leak with events.
  • @pst 抱歉,我使用的是 jQuery 1.7.1。我认为这是隐含的,因为它包含在 jsfiddle 示例中。我不确定 Chrome 版本是否相关。我的意思是问题似乎不是特定于浏览器的。

标签: javascript jquery browser memory-leaks


【解决方案1】:

程序分配内存的情况并不少见,看到它的内存使用量上升,然后在释放内存时没有改变。这是底层操作系统如何管理内存的结果,不一定引起关注,也不一定是“问题”。一般来说,您应该使用其他工具来定位程序中的内存泄漏(无论它们是本机代码还是存在于浏览器中),而不是依赖于跟踪整体进程统计信息的系统工具。

【讨论】:

    【解决方案2】:

    您需要小心查看浏览器的内存使用情况。更准确的测试是多次运行代码,然后查看浏览器内存使用情况,然后再运行多次并比较新数字。

    通常,浏览器的行为方式不会反映 只是 javascript 的使用。因此,它的内存使用量可能会波动,而您的代码不一定会有泄漏。

    【讨论】:

      【解决方案3】:

      有一个技巧可以减少/避免内存泄漏,至少在 IE 中是这样。

      您可以试试看是否比您当前的方法更快地释放内存。
      就是先在DOM中插入HTML,再附加事件。

      【讨论】:

        【解决方案4】:

        我和ShaggyFrog 在这个问题上。您可以通过删除局部变量并在完成后手动清空 appendUs 数组来减少内存分配。在 Chrome 中,我看到每次运行脚本时内存分配都会增加 800KB - 1MB。如上所述制作small changes to your code 将每次运行的额外内存分配减少到 400 - 500KB(平均而言,通过手动观察任务管理器)。

        话虽如此,行为可能只是 Windows 和/或 Chrome 及其内存管理。在让 JSFiddle 页面闲置一段时间后,Chrome 的内存使用量下降到我开始运行您的示例之前的位置。某种垃圾收集最终发生了,只是可能没有您预期的那么快。

        【讨论】:

          【解决方案5】:

          这与 DOM 的 GC 和 JavaScript GC 不是朋友有关。基本要点是,如果 DOM 引用了某些东西,JS GC 可能不会销毁它,反之亦然。这个想法可能已经过时了,因为它出现在 Crockford 的书中,该书比浏览器老了几代。

          我在这里看到了一些潜在的问题,这可能是 JS Fiddle 特有的,但可能不是:

          • 是否需要指定 F?
          • 您在这里一次创建大量 DOM 元素,
          • 您在每次运行时都在重新创建 F,因此问题更可能出现在 DOM 的 GC 中,而不是 JavaScript 的 GC 中
          • JavaScript 的 GC 是一种标记和清除扫描器,这意味着它是“惰性的”。您可以在您的脚本中看到这一点 - 如果您运行它十次,内存使用量会急剧上升,但最终废弃的对象会被垃圾收集并且内存使用量会下降。
          • 您需要担心的闭包是分配给 click 元素的闭包,但您在这里没有使用闭包。

          但我没有发现任何真正的问题,几分钟后我的内存使用量恢复正常。

          简而言之,您没有内存泄漏(至少是紧迫的),您的 JS 解释器的 GC 只是懒惰。您放弃了很多 DOM 元素,这并不好,这也是您的内存激增的原因,但这是短期的性能损失,而不是长期的页面加载问题。

          【讨论】:

            猜你喜欢
            • 2012-01-13
            • 2021-08-02
            • 2011-09-22
            • 2011-08-08
            • 2011-03-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多