2013-09-02 7 views
5

Tło: Zainspirowany this question i this question o wykorzystaniu pamięci D3 postanowiłem zagłębić się jak to naprawdę działa, a wkrótce przyszło na cautions about repeated add/remove of DOM nodes in IE.Dlaczego moje węzły SVG wyciek pamięci w IE

Aby odizolować od czegokolwiek innego D3 robił, po raz pierwszy spróbował podstawową sprawę SVG dodawania/usuwania 1000 kręgi co drugi:

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

Okazało się, że to powoli wycieka pamięć zarówno IE9 i IE10. Zobacz tutaj w wersji na żywo: http://bl.ocks.org/explunit/6413259

Co (jeśli w ogóle) można zrobić, aby uniknąć wycieku i jakie skutki to ma za jaki kod D3 kierowania IE powinno być napisane, że dodaje/usuwa wiele węzłów?

Inne uwagi:

Zainspirowany this article starałem proste podejście basen węzeł wciskając usuniętych węzłów na stosie:

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

i ponownego ich później:

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 
} 

Ale to nie miało znaczenia.

Odpowiedz

2

Jedyne co znalazłem tak daleko, że pomaga w wykorzystaniu pamięci IE jest nie przypisywać identyfikatory do węzłów lub przypisać im identyfikatory, które powtarzają się w różnych iteracji animacji:

node.id = 'id' + j; 

Zobacz wersję na żywo tutaj: http://bl.ocks.org/explunit/6413371

Myślałem, że zerowanie identyfikatora przed usunięciem węzła DOM spowoduje to samo, ale nie przyniosło to efektu.

Nie podoba mi się ta odpowiedź, więc mam nadzieję, że ktoś inny przedstawi lepsze wyjaśnienie, dlaczego metoda puli węzłów nie działa.

Ale na razie, morał historii dla programistów używających D3: jeśli wielokrotnie dodajesz i usuwasz wiele węzłów z unikalnymi identyfikatorami (np. Z wywołań .ajax, które pobierają rekordy z db), możesz być w niebezpieczeństwie wycieku pamięci.