为什么jquery泄漏内存如此糟糕?

时间:2010-03-15 21:53:21

标签: jquery ajax memory memory-leaks

这是我上周发布的一个问题的后续行动: Simple jQuery Ajax call leaks memory in Internet Explorer

我喜欢jquery语法及其所有不错的功能,但我一直遇到一个页面问题,该页面通过ajax调用泄漏内存自动更新表格单元格。

所以我创建了两个简单的测试页面进行实验。两个页面每隔0.1秒进行一次ajax调用。在每次成功调用ajax之后,计数器会递增并更新DOM。脚本在1000次循环后停止。

一个使用jquery进行ajax调用和更新DOM。另一个使用Yahoo API作为ajax,并使用document.getElementById(...)。innerHTML来更新DOM。

jquery版本严重泄漏内存。滴水运行(在带有IE7的XP Home上),从9MB开始,大约48MB,内存随时间线性增长。如果我注释掉更新DOM的行,它仍然会以32MB结束,这表明即使是简单的DOM更新也会泄漏大量内存。无论是否更新DOM,非jquery版本的启动和完成大约为9MB。

有没有人能够很好地解释导致jquery如此严重泄漏的原因?我错过了一些明显的东西吗是否有我不知道的循环引用?或者jquery是否只有一些严重的内存问题?

以下是leaky(jquery)版本的源代码:

<html>
  <head>
    <script type="text/javascript" src="http://www.google.com/jsapi"></script>
    <script type="text/javascript">
      google.load('jquery', '1.4.2');
    </script>
    <script type="text/javascript">
      var counter = 0;
      leakTest();
      function leakTest() {
        $.ajax({ url: '/html/delme.x',
                 type: 'GET',
                 success: incrementCounter
               });
      }
      function incrementCounter(data) {
        if (counter<1000) {
          counter++;
          $('#counter').text(counter);
          setTimeout(leakTest,100);
        }
        else $('#counter').text('finished.');
      }
    </script>
  </head>
  <body>
    <div>Why is memory usage going up?</div>
    <div id="counter"></div>
  </body>
</html>

这是非泄漏版本:

<html>
  <head>
    <script type="text/javascript" src="http://yui.yahooapis.com/2.8.0r4/build/yahoo/yahoo-min.js"></script>
    <script type="text/javascript" src="http://yui.yahooapis.com/2.8.0r4/build/event/event-min.js"></script>
    <script type="text/javascript" src="http://yui.yahooapis.com/2.8.0r4/build/connection/connection_core-min.js"></script>
    <script type="text/javascript">
      var counter = 0;
      leakTest();
      function leakTest() {
        YAHOO.util.Connect.asyncRequest('GET',
                                        '/html/delme.x',
                                        {success:incrementCounter});
      }
      function incrementCounter(o) {
        if (counter<1000) {
          counter++;
          document.getElementById('counter').innerHTML = counter;
          setTimeout(leakTest,100);
        }
        else document.getElementById('counter').innerHTML = 'finished.'
      }
    </script>
  </head>
  <body>
    <div>Memory usage is stable, right?</div>
    <div id="counter"></div>
  </body>
</html>

1 个答案:

答案 0 :(得分:8)

我最初的想法是它与jquery ajax方法的方式有关:

一个。创建循环引用,尤其是IE

湾在内部对象上创建属性,这些属性由于它们的创建方式和DontDelete属性的设置而无法删除。有关详情,请参阅此处:http://perfectionkills.com/understanding-delete/

无论哪种方式,都会阻止垃圾收集器拾取垃圾,这会导致内存泄漏,特别是如果可疑的功能正在频繁执行。