web-dev-qa-db-ja.com

jqueryがメモリをそれほどひどくリークするのはなぜですか?

これは、先週投稿した質問のフォローアップのようなものです: 単純なjQuery Ajax呼び出しでInternetExplorerのメモリリークが発生します

私はjquery構文とそのすべてのNice機能が大好きですが、メモリリークを伴うajax呼び出しを介してテーブルセルを自動的に更新するページで問題が発生しています。

そこで、実験用に2つの簡単なテストページを作成しました。どちらのページも、0.1秒ごとにajax呼び出しを実行します。 ajax呼び出しが成功するたびに、カウンターがインクリメントされ、DOMが更新されます。スクリプトは1000サイクル後に停止します。

Ajax呼び出しとDOMの更新の両方にjqueryを使用します。もう1つは、ajaxにYahoo APIを使用し、document.getElementById(...)。innerHTMLを実行してDOMを更新します。

Jqueryバージョンはメモリをひどくリークします。ドリップで実行すると(XP Home with IE7)、9MBで始まり、約48MBで終わり、メモリは常に直線的に増加します。DOMを更新する行をコメントアウトすると、それでも32MBで終了し、単純なDOM更新でもかなりの量のメモリがリークすることを示唆しています。jquery以外のバージョンは、DOMを更新するかどうかに関係なく、約9MBで開始および終了します。

誰かがjqueryがそれほどひどくリークする原因についての良い説明を持っていますか?明らかな何かが欠けていますか?私が知らない循環参照はありますか?それとも、jqueryには深刻なメモリの問題がありますか?

リーク(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>
63
Thomas Lane

私の最初の考えは、jqueryajaxメソッドの方法と関係があるということです。

a。特にIEに悪い循環参照を作成します

b。内部オブジェクトの作成方法とDontDeleteプロパティの設定により、削除できないプロパティを作成します。詳細については、こちらをご覧ください: http://perfectionkills.com/understanding-delete/

いずれにせよ、ガベージコレクターがゴミを拾うのを防ぎ、特にその疑わしい関数が頻繁に実行されている場合は、メモリリークが暴走します。

8
Jessica Jacobs