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

Поиск утечки памяти JS в инструментах chrome dev

Im, используя инструменты chrome dev, чтобы работать, если в некотором JS-коде есть утечка памяти. временная шкала памяти отлично смотрится с возвратом памяти, как ожидалось.

enter image description here

Тем не менее, моментальный снимок памяти запутан, потому что он похож на утечку, потому что есть записи в разделе "Detached DOM Tree".

Является ли материал под "Detached DOM Tree" просто ожидающим сбора мусора или это настоящие утечки?

Также кто-нибудь знает, как узнать, какая функция держится за ссылку на отдельный элемент?

enter image description here

4b9b3361

Ответ 1

Эти элементы ссылаются на ваш код, но они отключены от главного дерева DOM страницы.

Простой пример:

var a = document.createElement("div");

a теперь ссылается на отключенный элемент, он не может быть GC'd, когда a все еще находится в области видимости.

Если отдельные диски сохраняются в памяти, вы сохраняете ссылки на них. С jQuery это довольно просто сделать, просто сохраните ссылку на пройденный результат и сохраните это. Например:

var parents = $("span").parent("div");
$("span").remove();

Теперь прокручиваются ссылки, даже если они не отображаются, вы все равно ссылаетесь на них. parents косвенно поддерживает ссылки ко всем пролетам через свойство jQuery .prevObject. Поэтому parents.prevObject даст объект, который ссылается на все промежутки.

См. пример здесь http://jsfiddle.net/C5xCR/6/. Несмотря на то, что прямо не указано, что на промежутки будут ссылаться, на них на самом деле ссылается глобальная переменная parents, и вы можете видеть, что 1000 прогонов в дереве Detached DOM никогда не исчезают.

Теперь здесь один и тот же jsfiddle, но с:

delete parents.prevObject

И вы можете видеть, что промежутки больше не находятся в отдельно стоящем дереве деревьев или где-то в этом роде. http://jsfiddle.net/C5xCR/7/

Ответ 2

Является ли материал под "Detached DOM Tree" просто ожидающим сбора мусора или это настоящие утечки?

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

Также кто-нибудь знает, как узнать, какая функция держится за ссылку на отдельный элемент?

В одном и том же дереве DOM должен быть элемент (или несколько из них) с желтым фоном. Такие элементы ссылаются на код JavaScript. Вы можете узнать, кто именно сохраняет ссылку на элемент в дереве хранителей.

Ответ 3

Поскольку вы добавили тег jQuery, у меня было подозрительное подозрение, что это вещь jQuery. Быстрый google привел меня в эту страницу. При использовании метода jQ detach ссылка на объект по-прежнему сохраняется в памяти, поэтому это может привести к созданию моментального снимка.

Другое дело, что jQuery имеет div node под рукой, который, как правило, хранится в памяти, но никогда не добавляется к фактическому dom... своего рода document.createNode('div'), не добавляя его. Это тоже будет отображаться в снимке памяти. Вы не можете обойти это, jQuery использует его для анализа строк в html-элементах.

Итак, чтобы удалить некоторые элементы из памяти, используйте метод jQuery .remove(), и ваш mem будет немедленно очищен.cf. Esailija комментирует, почему remove не совсем соответствует счету здесь.
$('#someElem')[0].parentNode.removeChild($('#someElem')[0]); Следует удалить элемент целиком, но не может отменить события. Возможно, что-то вроде:

$('#someElem').detach();//to remove any event listeners
$('#someElem')[0].parentNode.removeChild($('#someElem')[0]);//remove element all together

И снова, как отметил в своем ответе Esailija, убедитесь, что вы привязываете ссылки на любой объект jQuery (var someRef= $('.someSelector');) на глобальную переменную, так как они не будут GC'ed. На самом деле просто избегайте глобальных сражений.
Но чтобы ответить на ваш вопрос кратко и четко: нет, это не настоящие утечки памяти, память должна быть освобождена в событии onbeforeunload. Объект jQuery удаляется, поэтому все ссылки выходят за рамки. По крайней мере, это то, что меня вдохновляло мое "исследование". Возможно, не совсем релевантно, но просто как ссылка Здесь вопрос о mem-утечках, который я опубликовал некоторое время назад, и с ним несколько вещей, которые я узнал.