javascript chrome - Экземпляры, на которые ссылается только «bound_this», не собираются мусором




2 Answers

Ваши подозрения, что это не настоящая утечка памяти, а странность с хромом, верна.

Недавно я столкнулся с той же проблемой. IE11 не будет показывать this.func = _.bind (this.func, this) как утечку памяти, в то время как хром будет, даже после того, как вы нажмете кнопку сбора мусора 100 раз.

Он покажет его даже после того, как вы запустите хром с помощью jsflag ерунды и выложите базовый сборщик мусора и вызовите gc 100 раз.

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

В экземпляре, которому назначена связанная функция, назначается новое свойство, подобное этому:

target.WhyAmILeaking = новый массив (200000000) .join ("YOURNOT");

Сделайте три моментальных снимка с помощью хром, и вы увидите, что строка присутствует в куче, которая работает с частотой около 214 МБ. Сделайте еще что-нибудь конструктивное действие (второй снимок), и вы увидите, что куча переместится на 423mb или останется на 214mb. Если он останется, вы закончите, так как вы доказали, что оригинальная 214mb была собрана. Если он не останется на вашем деструктивном действии (третий снимок), и он вернется к 214mb, также подтвердив, что оригинал собран.

Если он просто останется в 423 мб, у вас сэр или мадам есть утечка.

Ох и еще одна группа бедных душ, которые столкнулись с одной и той же ситуацией: https://github.com/jashkenas/backbone/issues/2269#issuecomment-13610969

TL; DR; используйте IE 11 для обнаружения утечек.

memory leak

У меня вопрос о сборке мусора в google chrome (версия 20.0.1132.47, Ubuntu 11.04 64 бит).

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

Взгляните на следующий снимок экрана

Экземпляр «child @ 610739» ссылается только на экземпляры «bound_this», которые относятся к функциям самого дочернего экземпляра. Поэтому, насколько я понимаю, дочерний экземпляр должен быть собран с помощью мусора, так как единственной другой ссылкой, поддерживающей его, является сам экземпляр-ребенок (через функции «bound_this»).

Я использую функцию утилиты underscore.js 'bindAll' ( underscore.js#bindAll ), которая сопоставляется с функцией «native_bind» хром ( вики-скрипт ECMA Script on bound_this )

Я пропустил что-то очевидное здесь, и если да, может кто-нибудь объяснить, что поддерживает эти случаи?

ОБНОВИТЬ:
Тем временем я тестировал одно и то же приложение в хрониуме (18.0.1025.168 (Developer Build 134367 Linux) Ubuntu 11.10), который не показывает эти оборванные экземпляры.

ОБНОВЛЕНИЕ 2:
Следуя указаниям Esailijas, чтобы предоставить фрагмент jsfiddle, я создал один ( http://jsfiddle.net/8gSTR/1/ ), который имитирует то, что я в основном делаю. К сожалению, запуск этой скрипки не показывает того, что я испытываю в своем приложении. Дамп кучи, сделанный в то время, когда «a» -экземпляры по-прежнему ссылаются, выглядит похожим, хотя, несмотря на ссылку из массива window.o, который сохраняет экземпляры в живых:

Поскольку такая ссылка отсутствует в моем случае (снимок экрана 1), я не знаю, что держит хром от освобождения этих экземпляров ...

ОБНОВЛЕНИЕ 3:
Следуйте совету loislos, чтобы включить скрытые свойства. Результат (с одним из ветвей расширены) можно увидеть на следующем скриншоте, но это не требует меня.




Вы запускаете «принудительный GC» с помощью инструментов разработчика? Если это так, и объекты сохраняются, то исследование выше имеет значение.

Если вы не запускаете GC через инструменты разработчика, помните, что способ работы GC-сервера довольно сложный и имеет концепцию коллекций поколений (с использованием двух поколений).

http://www.html5rocks.com/en/tutorials/memory/effectivemanagement/#toc-v8-gc

Просто может быть, что вы не достигли необходимого порога для запуска GC нового поколения или что объекты были привязаны к старому поколению, но что GC старого поколения никогда не запускался.

К сожалению, инструменты разработчика не показывают, какое поколение было GC'd.




Related

javascript google-chrome memory memory-leaks google-chrome-devtools