【发布时间】:2014-07-18 13:23:33
【问题描述】:
我正在开发一个创建和删除大量 DOM 的应用程序。我注意到浏览器选项卡中的进程内存不断增加,尽管 javascript 堆内存保持不变。在一个测试应用程序中,我从父 div 创建和删除 div。
<button onclick="createStuff()">Create</button>
<button onclick="deleteStuff()">Delete</button>
<div id="parent"></div>
function createStuff() {
var parentDiv = document.getElementById('parent');
for (var i = 0; i < 50000; i++) {
var child = document.createElement('div');
child.id = i;
child.textContent = i;
parentDiv.appendChild(child);
child = null;
}
parentDiv = null;
}
function deleteStuff() {
var parentDiv = document.getElementById('parent');
for (var i = 0; i < 50000; i++) {
var child = document.getElementById(i);
parentDiv.removeChild(child);
child = null;
}
parentDiv = null;
}
我已经确认 chrome 开发工具没有泄漏 javascript 堆(我是他们的新手,所以我可能会遗漏一些东西)。然而,进程的内存继续增加。从我读过的所有内容中,我怀疑已删除的 dom 仍在 dom 堆中。
其他帖子还说浏览器最终将释放分配给已删除 dom 的内存。在上面的 jsfiddle 示例中,我多次点击创建和删除。我的 javascript 堆稳定在 4.9MB。我的进程内存高达 115MB。我已经等了 30 分钟,它根本没有掉下来。
问题
- 何时从浏览器进程内存中完全删除 DOM 元素?
- 有没有办法强制 DOM 垃圾回收?
- 是否有工具可以更深入地了解哪些 dom 被标记为垃圾回收?我在 Chrome 或 IE 中找不到。
感谢您的帮助!
编辑
我使用了 chrome 开发工具,但 javascript 堆没有增长。有趣的是,堆快照之间唯一变化的是(数组)对象。我的理解是括号中的任何内容都由浏览器控制并且超出了我的范围。每个后续的 create->delete 都会删除旧的(数组)对象并在删除期间创建一个新对象。
在时间线中,我可以看到 javascript 堆是恒定的,并且节点被清理,但 (shift + esc) 所示的内存即使在节点数下降后也不会下降。
似乎我正在尽我所能确保清理我的 javascript 堆,但 dom 清理超出了我的能力范围,并且独立于 javascript GC。这种说法正确吗?
被移除的dom是年轻代堆的一部分吗?有没有办法设置这个堆大小的限制?我重复了测试,直到达到 500MB 并且仍然没有清理。我正在使用 Chrome 35.0.1916.114 顺便说一句。
【问题讨论】:
-
仅供参考,您不必
null输出局部变量。当函数完成时,它们将被自动处理(只要没有创建闭包来保持作用域活动——这在你的两个函数中没有)。 -
您可以在 chrome 开发工具 > 时间线 > 开始录制中尝试,在内存选项卡中您可以看到创建/删除时堆内存的增加...。顶部还有一个按钮“收集垃圾”...当您单击它时,您可以看到堆内存使用量的减少
-
浏览器会为你做这件事。
-
@r2_118 等待很长时间可能不会触发垃圾收集器。当浏览器的年轻代被填满时,它会进行垃圾回收。 html5rocks.com/en/tutorials/memory/effectivemanagement
-
我刚刚注意到您正在使用 Chrome 任务管理器来诊断您的内存问题。此视图只能告诉您您的应用程序使用了大量内存。您只能通过 javascript/dom/plugin/etc 内存使用来间接控制应用程序使用的内存量。因为您的应用程序使用了大量内存,所以 chrome 给了它很多内存是合适的(它很可能会再次需要它)。如果内存是泄漏的结果,这只是一个问题。从你发布的时间线 > 内存截图来看,看起来一切都被回收了
标签: javascript html dom memory-management memory-leaks