Поиск утечки памяти JS в инструментах chrome dev
Im, используя инструменты chrome dev, чтобы работать, если в некотором JS-коде есть утечка памяти. временная шкала памяти отлично смотрится с возвратом памяти, как ожидалось.
![enter image description here]()
Тем не менее, моментальный снимок памяти запутан, потому что он похож на утечку, потому что есть записи в разделе "Detached DOM Tree".
Является ли материал под "Detached DOM Tree" просто ожидающим сбора мусора или это настоящие утечки?
Также кто-нибудь знает, как узнать, какая функция держится за ссылку на отдельный элемент?
![enter image description here]()
Ответы
Ответ 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-утечках, который я опубликовал некоторое время назад, и с ним несколько вещей, которые я узнал.