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

Экземпляры, на которые ссылается только "bound_this", не собираются мусором

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

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

Взгляните на следующий снимок экрана Screenshot of heap-dump showing an instance (child) referenced only by 'bound_this'

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

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

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

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

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

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

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

4b9b3361

Ответ 1

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

Недавно я столкнулся с одной и той же проблемой. 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 для обнаружения утечек.

Ответ 2

Я упомянул это в EcmaScript, этот термин "связал это" с классом,

Методы класса "привязали это", где это в теле метода всегда привязано к экземпляру класса, из которого был извлечен метод, независимо от того, что этот параметр фактически передан методу (этот параметр для метода игнорируется).

Теперь здесь, в вашем примере нет образца script, поэтому не может быть конкретным для вопроса,

Я должен сказать, если это не утечка.

то с тем, что когда-либо объект, класс script ограничен, он не будет вызывать мусор до тех пор, пока не будет существовать класс/объект, поскольку эта функция ограничена одним и тем же объектом.. он будет мусором, собранным только после его родительского объекта (объект/класс, с которым он ограничен) область действия заканчивается.

Теперь, если круговая ссылка, когда задача завершится, будет завершена, → это работает, как концепция Recursion (помните, что это концепция, не такая же), поэтому конец будет начинаться с последнего вызова.. в обратном порядке.. внутренний вызов (последний вызов) будет выпущен первым.. и т.д.

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

Надеюсь, это объяснит.

Ответ 3

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

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

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

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

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