背景: this questionとthis question about D3 memory usage に触発されて、それが実際にどのように機能するかを掘り下げることにしました。
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
}
しかし、これは何の違いもありませんでした。