背景:受这个问题和这个关于 D3 内存使用的问题的启发,我决定深入研究它是如何工作的,很快就发现了关于在 IE 中重复添加/删除 DOM 节点的警告。
为了与 D3 所做的其他事情隔离开来,我首先尝试了每秒添加/删除 1000 个圆圈的基本 SVG 案例:
var count = 1000;
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute('width', '800');
svg.setAttribute('height', '800');
document.body.appendChild(svg);
function update() {
// remove existing circles
var circles = svg.querySelectorAll("circle")
for (var i = circles.length - 1; i >= 0; i--) {
var parent = circles[i].parentNode;
if (parent) parent.removeChild(circles[i]);
};
// add new ones. Yes, would make more sense to update the x,y on the existing
// circles but this is to show what happens in IE with lots of nodes being added/removed
for (var j = count - 1; j >= 0; j--) {
var node = document.createElementNS("http://www.w3.org/2000/svg", 'circle');
node.id = 'id' + Math.random();
node.setAttributeNS(null, "cx", Math.random()*800);
node.setAttributeNS(null, "cy", Math.random()*800);
node.setAttributeNS(null, "r", 5);
node.setAttributeNS(null, "fill", "blue");
svg.appendChild(node);
};
}
setInterval(update, 1000);
我发现这会在 IE9 和 IE10 中缓慢泄漏内存。现场版本见这里:http: //bl.ocks.org/explunit/6413259
我可以做些什么(如果有的话)来防止泄漏,这对如何编写针对 IE 的 D3 代码添加/删除大量节点有什么影响?
其他注意事项:
受这篇文章的启发,我尝试了一种简单的节点池方法,将移除的节点推送到堆栈中:
if (parent) circlePool.push( parent.removeChild(circles[i]) );
并在以后重用它们:
var node;
if (circlePool.length == 0) {
node = document.createElementNS("http://www.w3.org/2000/svg", 'circle');
} else {
node = circlePool.pop();
//TODO: clear out attributes of the node
}
但这没有任何区别。