Почему JQuery так сильно теряет память? - PullRequest
63 голосов
/ 16 марта 2010

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

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

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

Один использует jquery как для вызова ajax, так и для обновления DOM. Другой использует Yahoo API для 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>

1 Ответ

8 голосов
/ 29 марта 2011

Первоначально я думал, что это как-то связано с методом jquery ajax:

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...