5

背景: this questionthis 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
}

しかし、これは何の違いもありませんでした。

4

1 に答える 1

2

私がこれまでに見つけた IE のメモリ使用に役立つ唯一の方法は、ノードに ID を割り当てないこと、またはアニメーションの繰り返しで繰り返される ID をノードに割り当てることです。

node.id = 'id' + j;

ここでライブバージョンを参照してください: http://bl.ocks.org/explunit/6413371

DOM ノードを削除する前に ID を null にすれば同じことができると思いましたが、効果はありませんでした。

私はこの答えがあまり好きではないので、他の誰かがノードプールアプローチがうまくいかなかった理由についてより良い説明をしてくれることを願っています.

しかし今のところ、D3 を使用する開発者にとっての教訓: 一意の ID を持つ多数のノードを繰り返し追加してから削除すると (たとえば、db からレコードを取得する .ajax 呼び出しから)、危険にさらされる可能性があります。メモリーリーク。

于 2013-09-02T14:26:19.883 に答える