Подтвердить что ты не робот

Почему у jquery утечка памяти так плохо?

Это будет следствием вопроса, который я опубликовал на прошлой неделе: Простой jQuery Ajax вызывает утечку памяти в Internet Explorer

Мне нравится синтаксис jquery и все его приятные функции, но у меня возникли проблемы со страницей, которая автоматически обновляет ячейки таблицы через ajax-вызовы, утечка памяти.

Итак, я создал две простые тестовые страницы для экспериментов. Обе страницы выполняют ajax-вызов каждые 0,1 секунды. После каждого успешного вызова ajax счетчик увеличивается и DOM обновляется. script останавливается после 1000 циклов.

Один использует jquery для вызова ajax и для обновления DOM. Другой использует API Yahoo для ajax и делает document.getElementById(...). InnerHTML для обновления DOM.

В версии jquery плохо протекает память. Запуск в капельке (на XP Home с IE7) начинается с 9 МБ и заканчивается примерно на 48 МБ, при этом память растет линейно все время. Если я прокомментирую строку, которая обновляет DOM, она по-прежнему заканчивается на 32 МБ, предполагая, что даже простые обновления DOM утечки значительного объема памяти. Версия не-jquery начинается и заканчивается примерно на 9 МБ, независимо от того, обновляет ли она DOM.

Есть ли у кого-нибудь хорошее объяснение того, что приводит к тому, что 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>
4b9b3361

Ответ 1

Моя первоначальная мысль заключалась в том, что она имеет какое-то отношение к способу jQuery ajax:

а. создает циклические ссылки, особенно плохо для IE

б. создает свойства на внутренних объектах, которые невозможно удалить из-за того, как они были созданы, и настройки свойства DontDelete. См. Это для получения дополнительной информации: http://perfectionkills.com/understanding-delete/

В любом случае сборщику мусора было бы запрещено собирать мусор, что приведет к утечке утечки памяти, особенно если эта подозрительная функция выполняется часто.