Javascript 何时从内存中删除DOM?
我正在开发一个正在创建和删除大量DOM的应用程序。我注意到浏览器选项卡中的进程内存不断增加,尽管javascript堆内存保持不变。在测试应用程序中,我从父div创建并删除divJavascript 何时从内存中删除DOM?,javascript,html,dom,memory-management,memory-leaks,Javascript,Html,Dom,Memory Management,Memory Leaks,我正在开发一个正在创建和删除大量DOM的应用程序。我注意到浏览器选项卡中的进程内存不断增加,尽管javascript堆内存保持不变。在测试应用程序中,我从父div创建并删除div 创建 删除 函数createStuff(){ var parentDiv=document.getElementById('parent'); 对于(变量i=0;i
创建
删除
函数createStuff(){
var parentDiv=document.getElementById('parent');
对于(变量i=0;i<50000;i++){
var child=document.createElement('div');
child.id=i;
child.textContent=i;
parentDiv.appendChild(儿童);
child=null;
}
parentDiv=null;
}
函数deleteStuff(){
var parentDiv=document.getElementById('parent');
对于(变量i=0;i<50000;i++){
var child=document.getElementById(i);
父母子女(子女);
child=null;
}
parentDiv=null;
}
我已经确认,chrome开发工具没有泄漏javascript堆(我是新手,所以我可能错过了一些东西)。但是,进程的内存继续增加。从我所读到的一切来看,我怀疑被删除的dom仍然在dom堆中
其他帖子还说,浏览器最终将释放分配给已删除DOM的内存。在上面的JSFIDLE示例中,我多次点击了create和delete。我的javascript堆稳定在4.9MB。我的进程内存高达115MB。我等了30分钟,它一点也没掉下来
问题
被删除的DOM是年轻一代堆的一部分吗?有没有办法设置此堆大小的限制?我重复测试,直到达到500MB,仍然没有清理。我使用的是Chrome 35.0.1916.114顺便说一句。浏览器应该注意这一点。113MB的内存仍然很低 但是作为一个例子,请考虑这一点:
创建
删除
var parentDiv=document.querySelector(“#parent”);
var操作={
创建:函数createStuff(){
var frag=document.createDocumentFragment();
对于(变量i=0;i<10000;i++){
var child=document.createElement('div');
child.id=i;
child.textContent=i;
附肢儿童(child);
}
亲子分部(frag);
},
delete:函数deleteStuff(){
while(parentDiv.childrence.length)parentDiv.removeChild(parentDiv.firstChild);
}
};
Array.prototype.forEach.call(document.queryselectoral('button'),函数addListener(el){
el.addEventListener('click',函数处理程序(事件){
console.log(event.target.textContent+“!”);
操作[event.target.className]();
});
});
我知道你问过Chrome,但我会介绍它在Firefox中的工作原理,希望你和其他读者会感兴趣。我不确定Chrome是否也能起到类似的作用
在您的测试用例中,Firefox内存使用不会持续增加。只有在第一次创建/删除元素时,内存使用才会永久增加在随后的创建/删除周期中,所有分配的内存随后都会被回收。
至少在Firefox中,你不能在不重新加载页面的情况下强制释放内存。如果您确实需要暂时分配这么多内存,那么您应该在一个iframe中进行分配,完成后可以扔掉
技术细节如下:
在Firefox中,有一个用于检查内存使用情况的工具,名为。它按类别划分已使用的内存,并具有强制清除内存的控件(GC/CC/Minimize memory) 以下是创建/删除DOM元素以及GC启动后,
about:memory
的相关部分是如何处理的:
├──34.34 MB (03.30%) -- window(http://fiddle.jshell.net/PSxPz/2/show/)
│ ├──26.54 MB (02.55%) -- layout
│ │ ├──13.95 MB (01.34%) -- (8 tiny)
│ │ │ ├───7.63 MB (00.73%) ── line-boxes
│ │ │ ├───4.00 MB (00.38%) ── pres-contexts
│ │ │ ├───2.26 MB (00.22%) ── pres-shell
│ │ │ ├───0.04 MB (00.00%) ── style-structs
│ │ │ ├───0.01 MB (00.00%) ── rule-nodes
│ │ │ ├───0.01 MB (00.00%) ── style-contexts
│ │ │ ├───0.00 MB (00.00%) ── style-sets
│ │ │ └───0.00 MB (00.00%) ── text-runs
│ │ └──12.59 MB (01.21%) -- frames
│ │ ├───7.25 MB (00.70%) ── nsBlockFrame
│ │ ├───5.34 MB (00.51%) ── nsTextFrame
│ │ └───0.00 MB (00.00%) ── sundries
│ └───7.80 MB (00.75%) -- (4 tiny)
│ ├──7.51 MB (00.72%) ++ dom
│ ├──0.29 MB (00.03%) ++ js-compartment(http://fiddle.jshell.net/PSxPz/2/show/)
│ ├──0.00 MB (00.00%) ── style-sheets
│ └──0.00 MB (00.00%) ── property-tables
(如果DOM节点已从文档中删除,但尚未进行垃圾收集,则它们将显示在孤立节点下。)
大部分额外内存(创建DOM节点时请求的)保留用于布局
- 与其他浏览器一样,Firefox创建了一个独立的浏览器。这是一个实现细节,网页完全无法访问
- Gecko中的帧是从中分配的
- 当已经分配的空间无法容纳更多的帧时(首次创建50000个DOM元素时会发生这种情况),布局(所谓的PresShell)竞技场会从操作系统中分配额外内存,但在页面卸载之前,不要将其释放回操作系统。
这种行为基于测量结果,这些测量结果表明,现实生活中的网页在其生命周期中通常需要大约相同数量的布局对象:一个典型的网页并不像这里的测试用例那样,分配100000帧来销毁它们,而是显示一个非常简单的页面
这种内存管理行为在fra速度的提高中得到了回报
<button class="create">Create</button>
<button class="delete">Delete</button>
<div id="parent"></div>
<script>
var parentDiv = document.querySelector('#parent');
var actions = {
create: function createStuff() {
var frag = document.createDocumentFragment();
for (var i = 0; i < 10000; i++) {
var child = document.createElement('div');
child.id = i;
child.textContent = i;
frag.appendChild(child);
}
parentDiv.appendChild(frag);
},
delete: function deleteStuff() {
while (parentDiv.children.length) parentDiv.removeChild(parentDiv.firstChild);
}
};
Array.prototype.forEach.call(document.querySelectorAll('button'), function addListener(el) {
el.addEventListener('click', function handler(event) {
console.log(event.target.textContent + '!');
actions[event.target.className]();
});
});
</script>
├──34.34 MB (03.30%) -- window(http://fiddle.jshell.net/PSxPz/2/show/)
│ ├──26.54 MB (02.55%) -- layout
│ │ ├──13.95 MB (01.34%) -- (8 tiny)
│ │ │ ├───7.63 MB (00.73%) ── line-boxes
│ │ │ ├───4.00 MB (00.38%) ── pres-contexts
│ │ │ ├───2.26 MB (00.22%) ── pres-shell
│ │ │ ├───0.04 MB (00.00%) ── style-structs
│ │ │ ├───0.01 MB (00.00%) ── rule-nodes
│ │ │ ├───0.01 MB (00.00%) ── style-contexts
│ │ │ ├───0.00 MB (00.00%) ── style-sets
│ │ │ └───0.00 MB (00.00%) ── text-runs
│ │ └──12.59 MB (01.21%) -- frames
│ │ ├───7.25 MB (00.70%) ── nsBlockFrame
│ │ ├───5.34 MB (00.51%) ── nsTextFrame
│ │ └───0.00 MB (00.00%) ── sundries
│ └───7.80 MB (00.75%) -- (4 tiny)
│ ├──7.51 MB (00.72%) ++ dom
│ ├──0.29 MB (00.03%) ++ js-compartment(http://fiddle.jshell.net/PSxPz/2/show/)
│ ├──0.00 MB (00.00%) ── style-sheets
│ └──0.00 MB (00.00%) ── property-tables