为什么我的svg节点泄漏内存在IE [英] Why do my svg nodes leak memory in IE

查看:414
本文介绍了为什么我的svg节点泄漏内存在IE的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景:受到此问题此问题关于D3内存使用我决定深入研究它如何工作,很快就来了关于在IE中重复添加/删除DOM节点的注意事项



,我首先尝试基本的SVG情况下每秒添加/删除1000个圆:

  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(){
//删除现有的圆
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]);
};

//添加新的。是的,将更有意义的更新现有的
//圈子的x,y,但这是显示发生在IE中有很多节点被添加/删除
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

我可以做什么(如果有什么),以防止泄漏,以及这对于如何D3代码定位IE应写入增加/删除很多



其他注意事项:本文,我尝试了一个简单的节点池方法通过将删除的节点推到堆栈:

  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:清除节点的属性
}

没有任何区别。

解决方案

到目前为止,我发现的唯一帮助IE内存使用的是为节点分配ID,或者为其分配在动画重复时重复的ID:

 节点.id ='id'+ j; 

查看实时版本: http://bl.ocks.org/explunit/6413371



我认为在删除DOM节点会做同样的事情,但这没有效果。



我真的不喜欢这个答案,所以我希望别人一起来一个更好的解释为什么节点池方法不工作。



但是现在,对于开发人员使用D3的故事的道德:如果你反复添加和然后删除大量具有唯一ID的节点(例如,从可以从db中获取记录的.ajax调用),您可能有内存泄漏的危险。


Background: Inspired by this question and this question about D3 memory usage I decided to dig into how it really works, and soon came upon cautions about repeated add/remove of DOM nodes in IE.

To isolate from whatever else D3 was doing, I first tried the basic SVG case of adding/removing 1000 circles every second:

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);

I found that this slowly leaks memory in both IE9 and IE10. See here for live version: http://bl.ocks.org/explunit/6413259

What (if anything) can I do to prevent the leak, and what implications does this have for how D3 code targeting IE should be written that adds/removes a lot of nodes?

Other notes:

Inspired by this article, I tried a simple node pool approach by pushing the removed nodes on to a stack:

if (parent) circlePool.push( parent.removeChild(circles[i]) );

And reusing them later:

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
}

But this did not make any difference.

解决方案

The only thing I've found so far that helps with IE memory usage is to not assign IDs to the nodes, or to assign them IDs that repeat across iterations of the animation:

node.id = 'id' + j;

See the live version here: http://bl.ocks.org/explunit/6413371

I thought that nulling the ID prior to removing the DOM node would do the same thing, but this had no effect.

I don't really like this answer so I'm hoping that someone else comes along with a better explanation of why the node pool approach didn't work.

But for now, the moral of the story for developers using D3: if you're repeatedly adding and then removing lots of nodes with unique IDs (e.g. from .ajax calls which get records out of db), you might be in danger of a memory leak.

这篇关于为什么我的svg节点泄漏内存在IE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆