63

This is kind of a follow-up to a question I posted last week: Simple jQuery Ajax call leaks memory in Internet Explorer

I love the jquery syntax and all of its nice features, but I've been having trouble with a page that automatically updates table cells via ajax calls leaking memory.

So I created two simple test pages for experimenting. Both pages do an ajax call every .1 seconds. After each successful ajax call, a counter is incremented and the DOM is updated. The script stops after 1000 cycles.

One uses jquery for both the ajax call and to update the DOM. The other uses the Yahoo API for the ajax and does a document.getElementById(...).innerHTML to update the DOM.

The jquery version leaks memory badly. Running in drip (on XP Home with IE7), it starts at 9MB and finishes at about 48MB, with memory growing linearly the whole time. If I comment out the line that updates the DOM, it still finishes at 32MB, suggesting that even simple DOM updates leak a significant amount of memory. The non-jquery version starts and finishes at about 9MB, regardless of whether it updates the DOM.

Does anyone have a good explanation of what is causing jquery to leak so badly? Am I missing something obvious? Is there a circular reference that I'm not aware of? Or does jquery just have some serious memory issues?

Here is the source for the leaky (jquery) version:

<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>

And here is the non-leaky version:

<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>
Community
  • 1
  • 1
Thomas Lane
  • 1,111
  • 1
  • 9
  • 9
  • 2
    What version of jquery are you using? – Nathan Long Mar 15 '10 at 22:00
  • 1
    His snippets are loading 1.4.2 – Shay Erlichmen Mar 15 '10 at 22:03
  • Why exactly are you using v1.4?? It is possible, and actually pretty likely, that there was memory leaks in that version that are now fixed in the more recent versions – jyore Sep 14 '11 at 23:38
  • @jyore This question was asked in March of 2010, at which point jquery 1.4.2 had just been released the previous month. – Kevin B Sep 15 '11 at 15:30
  • Ah, I guess I overlooked the start date since I just saw it pop up on the bounty list. Still would be interested if the problem goes away when updating to the new jQuery – jyore Sep 15 '11 at 16:20
  • 2
    it should have been fixed in 1.5.0 with the ajax rewrite, it was a known bug that had a fix posted in the bug system. – Kevin B Sep 15 '11 at 20:58
  • Does this still occur with the latest version of jQuery? – b01 Sep 21 '11 at 17:09
  • I don't know whether this is still occurring with latest version of jQuery. But there are two significant differences between the above examples, which I would correct before being sure I could lay the blame with jQuery: (1) the jQuery example uses google's jsapi to load jquery, while the yahoo example loads yahoo's framework directly -both should load their respective libraries directly; (2) the yahoo example sets `innerHTML`, while the jQuery example uses `$.text(...)`, but a better jQuery translation of `innerHTML` would be `$.html(...)`. – Lee Sep 21 '11 at 19:25

1 Answers1

8

My initial thought would be that it has something to do with the way the jquery ajax method either:

a. creates circular references, especially bad for IE

b. creates properties on internal objects which cannot be deleted due to the way they have been created and the setting of the DontDelete property. See this for more info: http://perfectionkills.com/understanding-delete/

Either way, the garbage collector would be prevented from picking up the trash, which would result in a runaway memory leak, especially if that suspect function is executing frequently.

Jess Jacobs
  • 1,137
  • 1
  • 8
  • 19
  • This situation can happen inside node applications as well, mostly because of the use of variables declared in a parent function scope, used in a callback closure later. This can be prevented by de-referencing the objects after use: http://stackoverflow.com/questions/5733665/how-to-prevent-memory-leaks-in-node-js – Alex Mar 23 '15 at 15:46