Утечки памяти с замыканиями и (jQuery) DOM-событиями в текущих браузерах? - PullRequest
3 голосов
/ 07 декабря 2011

Я новичок в javascript и, похоже, у меня возникли проблемы с поиском утечки памяти. Я сузил его до раздела, который, кажется, вызывает утечку памяти, поскольку код довольно сложный. Я опубликую другой пример, который упрощает его, но вызывает ту же проблему (только намного меньше).

Пример кода

По сути, у меня есть некоторый код, который динамически создает HTML и присоединяет события к HTML. HTML перестраивается с каждым запросом AJAX. В первый раз все работает нормально, но после каждого AJAX-запроса память браузера увеличивается (не всегда одинаково)! Эту проблему можно воспроизвести, щелкнув несколько раз на jsfiddle и проследив за памятью браузера. Я предполагаю, что создаваемые замыкания никогда не собираются мусором, но я не уверен? Если это так, есть ли лучший способ сделать это без замыканий, которые не вызовут никаких проблем?

Это происходит в FF8, последней версии Chrome и IE 8. Скорее всего, во всех остальных - именно то, что я тестировал.

Я поместил в код некоторые комментарии, которые должны помочь.

Спасибо!

EDIT: Итак, после некоторого исследования с использованием sIEve я вижу, что количество DOM-узлов удваивается при каждом вызове AJAX. Я обновил пример, чтобы смоделировать это. Итак, мой вопрос: почему не выполняется сборка элементов DOM после вызова jQuery пустым или удаления функций? Я также просматривал элементы в материале, открепляя обработчики событий и устанавливая ссылку js каждого элемента DOM на ноль без последствий ...

Пример кода

Ответы [ 5 ]

3 голосов
/ 07 декабря 2011

Это связано с тем, что DOM GC и JavaScript GC не дружат.Основная суть в том, что если на что-то ссылается DOM, JS GC может не уничтожить это, и наоборот.Эта идея может быть устаревшей, так как она упоминается в книге Крокфорда, которая представляет собой несколько поколений старых браузеров.

Я вижу здесь несколько потенциальных проблем, которые могут быть специфическими для JS Fiddle, но могут не быть:1003 *

  • Нужно ли назначать F?
  • Вы создаете МНОГО элементов DOM здесь по одному,
  • Вы воссоздаете F при каждом запуске, поэтому проблема скорее в GC DOM, чем в JavaScriptGC
  • GC JavaScript - это сканер меток и разверток, что означает, что он «ленивый».Вы можете увидеть это в своем скрипте - если вы запускаете его десять раз, использование памяти резко возрастает, но в конечном итоге заброшенные объекты собирают мусор, а использование памяти снижается.
  • Закрытие, о котором вам нужно беспокоитьсяabout это тот элемент, который назначен элементу click, но вы здесь не используете замыкание.

Но я не вижу никаких реальных проблем, и через несколько минут использование моей памяти снова снижаетсяк нормальному.

Короче говоря, у вас нет утечки памяти (по крайней мере, неотложной), GC вашего интерпретатора JS просто ленится.Вы отказываетесь от большого количества элементов DOM, что нехорошо и является причиной скачка памяти, но это краткосрочный удар по производительности, а не долговременная проблема загрузки страницы.

1 голос
/ 07 декабря 2011

Программа нередко выделяет память, видит, как увеличивается ее использование, а затем не изменяется при освобождении этой памяти.Это является следствием того, как базовая ОС управляет памятью, и не обязательно вызывает беспокойство и не обязательно является «проблемой».В общем, вы должны использовать другие инструменты для обнаружения утечек памяти в программах (будь то встроенный код или встроенный браузер) вместо того, чтобы полагаться на системные инструменты, которые отслеживают общую статистику процесса.

0 голосов
/ 07 декабря 2011

Я с ShaggyFrog на этом.Вы можете уменьшить выделение памяти, удалив локальные переменные и очистив этот массив appendUs вручную, когда закончите с ним.В Chrome я видел увеличение объема памяти на 800 КБ - 1 МБ при каждом запуске вашего скрипта.Внесение небольших изменений в ваш код , как описано выше, уменьшило выделение дополнительной памяти до 400-500 КБ при каждом запуске (в среднем, путем ручного наблюдения диспетчера задач).Поведение может быть просто Windows и / или Chrome и их управление памятью.После некоторого простоя страницы JSFiddle использование памяти Chrome уменьшилось до того уровня, на котором оно было до того, как я начал запускать ваш пример.В конце концов, произошла какая-то сборка мусора, но, может быть, не так быстро, как вы ожидаете.

0 голосов
/ 07 декабря 2011

Был хитрость для уменьшения / предотвращения утечек памяти, по крайней мере, в IE.

Вы можете попробовать, чтобы увидеть, освобождается ли память быстрее, чем ваш текущий метод.Сначала вставьте HTML-код в DOM, а затем присоедините события.

0 голосов
/ 07 декабря 2011

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

Обычно браузер невести себя так, что отражает использование javascript.Таким образом, использование памяти может колебаться без утечки кода.

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