Почему jquery так сильно пропускает память?

Это своего рода продолжение вопроса, который я разместил на прошлой неделе: Простой вызов 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>

person Thomas Lane    schedule 15.03.2010    source источник
comment
Какую версию jquery вы используете?   -  person Nathan Long    schedule 16.03.2010
comment
Его фрагменты загружаются 1.4.2.   -  person Shay Erlichmen    schedule 16.03.2010
comment
Почему именно вы используете v1.4 ?? Возможно, и на самом деле весьма вероятно, что в этой версии были утечки памяти, которые теперь исправлены в более поздних версиях.   -  person jyore    schedule 15.09.2011
comment
@jyore Этот вопрос был задан в марте 2010 года, когда в предыдущем месяце был выпущен jquery 1.4.2.   -  person Kevin B    schedule 15.09.2011
comment
Ах, думаю, я пропустил дату начала, так как только что увидел ее в списке наград. По-прежнему было бы интересно, исчезнет ли проблема при обновлении до нового jQuery   -  person jyore    schedule 15.09.2011
comment
это должно было быть исправлено в 1.5.0 с помощью перезаписи ajax, это была известная ошибка, исправление которой было опубликовано в системе ошибок.   -  person Kevin B    schedule 16.09.2011
comment
Это все еще происходит с последней версией jQuery?   -  person b01    schedule 21.09.2011
comment
Я не знаю, происходит ли это по-прежнему с последней версией jQuery. Но между приведенными выше примерами есть два существенных различия, которые я бы исправил, прежде чем быть уверенным, что могу возложить вину на jQuery: (1) пример jQuery использует jsapi Google для загрузки jquery, тогда как пример yahoo загружает фреймворк yahoo напрямую - оба должны загружать соответствующие библиотеки напрямую; (2) пример yahoo устанавливает innerHTML, тогда как пример jQuery использует $.text(...), но лучший перевод jQuery для innerHTML будет $.html(...).   -  person Lee    schedule 21.09.2011


Ответы (1)


Моя первоначальная мысль заключалась в том, что это как-то связано с тем, как метод jquery ajax:

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

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

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

person Jess Jacobs    schedule 29.03.2011
comment
Эта ситуация также может происходить внутри узловых приложений, в основном из-за использования переменных, объявленных в области родительской функции, которые позже используются при закрытии обратного вызова. Этого можно избежать, сняв ссылку на объекты после использования: stackoverflow.com/questions/5733665/ - person Alex; 23.03.2015