我正在尝试使用Chrome Dev Tools来分析我的应用程序上的内存使用情况并检测泄露的DOM节点,并对我看到的一些行为感到困惑。根据{{3}},如果我创建DOM节点然后正确释放它们,该工具应该响应一个“Nodes”计数器,该计数器将重置为其基线:
但是如果预计行动序列不会导致任何保留的内存,并且DOM节点数不会下降回到您开始的基线,那么您有充分的理由怀疑存在泄漏。
方法:我使用了Chrome profiling docs的变体,修改后在节点内创建大字符串。
<html>
<head>
<script>
var leakedNodes = [];
var largeStr = new Array(1000000).join('x');
function createNode(text) {
var div = document.createElement("div"),
innerDiv = document.createElement("div"),
textNode = document.createTextNode(text + " - " + new Date().toTimeString() + "-" + largeStr);
innerDiv.appendChild(textNode);
div.appendChild(innerDiv);
return div;
}
function createLeakedNodes() {
var i;
for (i = 0; i < 200; i++) {
leakedNodes.push(createNode("Leaked:" + i));
}
}
function createGCNodes() {
var i;
for (i = 0; i < 200; i++) {
createNode("Collected:" + i);
}
}
function createNodes() {
createLeakedNodes();
createGCNodes();
}
function clearLeaks() {
leakedNodes = null;
}
</script>
</head>
<body>
<button onclick="createNodes()">Create</button>
<button onclick="clearLeaks()">Clear Leaks</button>
</body>
</html>
我在未启用扩展程序的隐身标签页面中启动该页面,启动开发工具,然后启动时间轴。我按下“创建”按钮三次,然后按“清除泄漏”按钮一次,然后单击分析器中的“收集垃圾”按钮强制GC,等待GC完成,然后停止时间线。
我查看了探查器中的“节点”计数器,并且在我按下“创建”按钮,然后在我单击“清除泄漏”按钮之后或之后,预计会看到它爬升的每一次我强迫GC。然而,我所看到的是图表爬升,但从未下降。
我对图表行为的理解是否不正确,或者节点是否合法地未被释放?如果是后者,上面的代码会导致泄漏,为什么相关内存显然是GCd符合预期?
答案 0 :(得分:3)
如果处理对数组的引用,似乎不会破坏对DOM节点的引用。但是如果你将数组的长度设置为零,那么数组中的所有元素都将被处理掉(因此所有对DOM元素的引用),然后垃圾收集器就可以完成它的工作并释放内存。 / p>
function clearLeaks() {
leakedNodes.length = 0;
}
我通过做一些研究并使用你的示例代码得到了这个结果:)。
答案 1 :(得分:1)
我认为Chrome开发工具中存在与DOM节点数相关的错误,如here所述。 在canary中分析代码确实会减少DOM数量。