随着时间的推移,使用过多内存的Ajax重JavaScript应用程序

5
我似乎在我正在开发的应用程序中有一些非常大的内存泄漏。 应用程序本身并不是很复杂。 每隔15秒,该页面从服务器请求约40kb的JSON数据,并使用它在页面上绘制表格。 通常情况下,重绘表格更便宜,因为数据通常是新的。 我将几个事件附加到表格上,每行大约5个,表格中有30行。 我使用jQuery的.html()方法将新html放入容器中并覆盖现有内容。 我这样做是为了让jQuery的特殊清理函数进入并尝试分离元素中的所有事件。 然后,我还使用delete my_var在将它们发送到DOM后删除大型HTML变量。
我已经检查了几次循环引用和永远不会清除的附加事件,但从未真正深入研究过。 我想知道是否有人可以给我一些关于如何优化这种非常重的应用程序的指针。 我刚刚看了Nicholas Zakas的“高性能Javascript”,但没有太多时间来深入研究它。
为了说明这使用了多少内存,4小时后,在Chrome上使用约420,000k,在Firefox或IE上使用更多。
谢谢!

3
为了得到有帮助的答案,您可能需要提供一个能够重现问题的代码示例。 - Chris Shouts
需要查看代码才能提供更多帮助。如果在FF中发生了,那么很有可能是由于未释放的资源或执行上下文引起的。旧版本的IE更容易受到DOM和JS引擎之间的“对象生命周期不匹配”的影响。请记住,即使您在执行上下文中重置数据,您也没有杀死执行上下文!(如果浏览器不释放从DOM中删除的元素的事件,那么这确实是一个bug。)这个bug听起来很有趣,请使用(最少的)测试用例进行更新:-) - user166390
我将尝试构建一个简单的JS文件,展示相同的症状。 - Shane Reustle
1
你使用的是哪个版本的jQuery? - Jason LeBrun
为了避免猜测:**(1)** 你使用的是 JSONP 还是 XMLHTTP(jQuery 中的默认设置)?**(2)** 响应看起来像什么?一个巨大的 HTML?序列化对象后转换成元素? - gblazex
使用最新稳定版本的jQuery,并且我正在使用getJSON。响应是一个JSON对象。 - Shane Reustle
7个回答

1

我也遇到过同样的问题。我有一段代码,每10秒轮询一次并获取当前用户错误(数据输入/审核)的计数,一个简单的整数。然后用它来替换div内的文本(这样用户就知道他们的工作中发现了新的错误)。如果让它过夜,浏览器最终会使用超过1GB的内存!

我最接近解决这个问题的方法是将轮询间隔减少到每2分钟,并坚持要求用户在一天结束时关闭浏览器。更好的解决方案是使用Ajax Push Engine,在创建错误时仅向页面推送数据。这将导致数据发送频率降低,从而减少内存使用。


很遗憾,我们确实需要每10-15秒更新所有数据。另外,由于这是一个“产品”,我们不能要求人们重新启动浏览器 :) 感谢您的建议。 - Shane Reustle

1
你有保存任何东西到对象/数组中吗?我之前用Chrome插件遇到过这种情况,其中一个数组不断变大。考虑到你正在获取40k,这听起来可能是你的问题所在。

该请求返回一个大的JSON对象,但它会覆盖同一变量中的先前对象。这将用新的内容覆盖相同的旧块。 - Shane Reustle

1

一个片段会很好,因为似乎每次都在创建新变量,旧变量没有超出范围,因此无法进行垃圾回收。

另外,尝试使用构造函数和对象实例来封装更多的JS。当JS只是一系列函数列表,所有变量都具有全局作用域而不是实例属性时,您的JS可能会占用大量内存。


1
为什么不只绘制一次表格并附加事件,然后每15秒替换表格数据呢?

1

1) Jquery Ajax包装器,被反复调用,会导致内存泄漏,社区已经意识到这一点(尽管Ajax包装器的问题远不如您的情况丑陋)。

2) 当涉及到优化时,您已经完成了第一步(使用轻量级json调用和删除方法),但问题在于“事件附加”区域和html方法。

我的意思是: 1)您可能在每次html()调用后重新附加侦听器 2)您在每个ajax调用中重新绘制整个表格。 这确实会导致内存泄漏。

您必须: 1)在服务器端绘制表格(带有第一次内容) 2)$(document).ready将侦听器附加到表格单元格 3)使用ajax调用json服务,解析响应 4)使用解析的数组数据重新填充表格

告诉我们您同时取得了什么成就 :)


1
我建议您编写一个没有事件的脚本测试版本。DOM / JS循环引用可能非常难以发现。通过从方程式中消除一些变量,您可能能够缩小搜索范围。

问题最终是我将谷歌图表附加到隐藏的弹出对话框中的每一行。一旦我删除了它,内存使用量就大大降低了。通过编写测试版本,我发现了这个问题。谢谢。 - Shane Reustle

0
这周我也遇到了类似的问题。结果发现我的数据库中存在循环引用。我有一个库存项目ABC123被标记为被XYZ321替换,而我也将XYZ321标记为被ABC123替换。有时候循环引用并不在PHP代码中。

当我说循环引用时,我指的是一个元素引用一个对象,该对象又引用相同的元素。请查看此文档:http://www.ibm.com/developerworks/web/library/wa-memleak/ - Shane Reustle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接