javascript 在 Chrome 开发工具中查找 JS 内存泄漏
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11930050/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Finding JS memory leak in chrome dev tools
提问by Carl Rippon
I'm using the chrome dev tools to work out if there is a memory leak in some JS code. The memory timelinelooks good with memory being reclaimed as expected.
我正在使用 chrome 开发工具来确定某些 JS 代码中是否存在内存泄漏。该内存时间表内存看起来不错预期被回收。
However, the memory snapshotis confusing because it appears like there is a leak because there are entries under “Detached DOM Tree”.
但是,内存快照令人困惑,因为它看起来像泄漏,因为“分离的 DOM 树”下有条目。
Is the stuff under “Detached DOM Tree” just waiting to be garbage collected or are these real leaks?
“分离的 DOM 树”下的东西只是在等待被垃圾收集还是这些真正的泄漏?
Also does anyone know how to find out what function is holding on to a reference to a detached element?
还有谁知道如何找出哪个函数保持对分离元素的引用?
采纳答案by Esailija
Those elements are being referenced in your code but they are disconnected from the page's main DOM tree.
这些元素在您的代码中被引用,但它们与页面的主 DOM 树断开连接。
Simple example:
简单的例子:
var a = document.createElement("div");
a
references a disconnected element now, it cannot be GC'd when a
is still in scope.
a
现在引用一个断开连接的元素,当a
它仍然在范围内时不能被 GC 。
If the detached dom trees persist in memory then you are keeping references to them. It is somewhat easy with jQuery to do this, just save a reference to a traversed result and keep that around. For example:
如果分离的 dom 树持续存在于内存中,那么您将保留对它们的引用。使用 jQuery 做到这一点有点容易,只需保存对遍历结果的引用并保留它。例如:
var parents = $("span").parent("div");
$("span").remove();
Now the spans are referenced even though it doesn't appear you are referencing them anyhow. parents
indirectly keeps references
to all the spans through the jQuery .prevObject
property. So doing parents.prevObject
would give the object that references all the spans.
现在跨度被引用,即使看起来你没有引用它们。parents
通过 jQuery.prevObject
属性间接保持对所有跨度的引用。这样做parents.prevObject
会给出引用所有跨度的对象。
See example here http://jsfiddle.net/C5xCR/6/. Even though it doesn't directly appear that the spans would be referenced,
they are in fact referenced by the parents
global variable and you can see the 1000 spans in the Detached DOM tree never go away.
请参阅此处的示例http://jsfiddle.net/C5xCR/6/。尽管看起来不会直接引用跨度,但实际上它们被parents
全局变量引用,您可以看到分离的 DOM 树中的 1000 个跨度永远不会消失。
Now here's the same jsfiddle but with:
现在这里有相同的 jsfiddle,但有:
delete parents.prevObject
And you can see the spans are no longer in the detached dom tree, or anywhere for that matter. http://jsfiddle.net/C5xCR/7/
你可以看到跨度不再在分离的 dom 树中,或者任何地方。http://jsfiddle.net/C5xCR/7/
回答by Yury Semikhatsky
Is the stuff under “Detached DOM Tree” just waiting to be garbage collected or are these real leaks?
“分离的 DOM 树”下的东西只是在等待被垃圾收集还是这些真正的泄漏?
Before taking snapshot the browser will run garbage collection and sweep all objects that are not referenced. So the heap snapshot always contain only live objects. As a consequence if a Detached DOM Tree is in the snapshot than there must be an element in the tree that is referenced from JavaScript.
在拍摄快照之前,浏览器将运行垃圾收集并清除所有未引用的对象。所以堆快照总是只包含活动对象。因此,如果一个分离的 DOM 树在快照中,那么树中必须有一个从 JavaScript 引用的元素。
Also does anyone know how to find out what function is holding on to a reference to a detached element?
还有谁知道如何找出哪个函数保持对分离元素的引用?
There should be an element(or several of them) in the same detached DOM tree that has yellow background. Such elements are referenced from the JavaScript code. You can find out who exactly keeps reference to the element in the retainers tree.
在具有黄色背景的同一个分离的 DOM 树中应该有一个(或其中几个)元素。这些元素是从 JavaScript 代码中引用的。您可以找出谁准确地保留了对保留树中元素的引用。
回答by Elias Van Ootegem
Since you've added the jQuery tag, I had a sneaky suspicion as to this being a jQuery thing. A quick google brought me to this page. When using jQ's detach
method, a reference to the object is still kept in memory, so that could be causing your snapshot.
由于您添加了 jQuery 标签,我偷偷怀疑这是 jQuery 的东西。一个快速的谷歌把我带到这个页面。使用 jQ 的detach
方法时,对对象的引用仍保留在内存中,因此可能会导致您的快照。
Another thing could be that jQuery has a div
node at hand, which is -obviously- kept in memory, but never added to the actual dom... a sort of document.createNode('div')
without appending it. This, too, will show up in the memory snapshot. You can't get around this, jQuery uses it to parse strings into html elements.
另一件事可能是 jQuerydiv
手头有一个节点,它 - 显然 - 保存在内存中,但从未添加到实际的 dom 中......有点document.createNode('div')
不附加它。这也将显示在内存快照中。您无法解决这个问题,jQuery 使用它来将字符串解析为 html 元素。
So to remove some elements from memory, use the jQuery .cf Esailija's comment on why .remove()
method, and your mem will be cleared instantlyremove
doesn't quite fit the bill here.$('#someElem')[0].parentNode.removeChild($('#someElem')[0]);
Should remove the element altogether, but might not unbind the events. Perhaps something along the lines of:
所以要从内存中删除一些元素,使用 jQuery。参见 Esalija 关于为什么.remove()
方法,你的内存将被立即清除remove
不完全符合这里的法案的评论。$('#someElem')[0].parentNode.removeChild($('#someElem')[0]);
应该完全删除元素,但可能不会取消绑定事件。也许是这样的:
$('#someElem').detach();//to remove any event listeners
$('#someElem')[0].parentNode.removeChild($('#someElem')[0]);//remove element all together
And, again, as Esailija pointed out in his answer, make sure that you assign references to any jQuery object (var someRef= $('.someSelector');
) to a global variable, as they won't be GC'ed. Just avoid globals all together, in fact.
But to answer your question briefly, and clearly: no these aren't realmemory leaks, the memory should be freed on the onbeforeunload
event. The jQuery object is deleted, so all references go out of scope. At least, That's what my "research"lead me to believe. Perhaps not entirely relevant, but just as a referenceHere's a question on mem-leaks I posted a while back, and with it a few things I found out..
而且,正如 Esailja 在他的回答中指出的那样,请确保将对任何 jQuery 对象 ( var someRef= $('.someSelector');
) 的引用分配给全局变量,因为它们不会被 GC 处理。事实上,只要避免全局变量。
但要简要地、明确地回答你的问题:不,这些不是真正的内存泄漏,应该在onbeforeunload
事件中释放内存。jQuery 对象被删除,因此所有引用都超出范围。至少,这就是我的“研究”使我相信的。也许不完全相关,但仅作为参考这是我不久前发布的关于内存泄漏的问题,并且通过它我发现了一些事情..