2013-09-02 145 views
5

Nền: Lấy cảm hứng từ this questionthis question về cách sử dụng bộ nhớ D3 Tôi quyết định tìm hiểu cách hoạt động của thiết bị và sớm xuất hiện trên cautions about repeated add/remove of DOM nodes in IE.Tại sao các nút svg của tôi bị rò rỉ bộ nhớ trong IE

Để cô lập từ bất cứ ai khác D3 đang làm, đầu tiên tôi thử các trường hợp SVG cơ bản của việc thêm/loại bỏ 1.000 vòng tròn mỗi giây:

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

tôi thấy rằng điều này từ từ rò rỉ bộ nhớ trong cả IE9 và IE10. Xem ở đây để biết phiên bản trực tiếp: http://bl.ocks.org/explunit/6413259

Tôi có thể làm gì nếu có bất kỳ điều gì có thể làm để ngăn chặn rò rỉ và điều này có nghĩa là gì?

ghi chú khác:

Lấy cảm hứng từ this article, tôi đã cố gắng một cách tiếp cận hồ bơi nút đơn giản bằng cách đẩy nút gỡ bỏ vào một ngăn xếp:

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

Và tái sử dụng chúng sau:

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 
} 

Nhưng điều này không tạo ra bất kỳ sự khác biệt nào.

Trả lời

2

Điều duy nhất tôi đã tìm thấy cho đến nay giúp với việc sử dụng bộ nhớ trình duyệt IE là không ID gán cho các nút, hoặc gán cho họ ID mà lặp lại trong các lần lặp của hoạt hình:

node.id = 'id' + j; 

Xem phiên bản trực tiếp tại đây: http://bl.ocks.org/explunit/6413371

Tôi nghĩ rằng việc hủy bỏ ID trước khi xóa nút DOM sẽ thực hiện tương tự, nhưng điều này không có hiệu lực.

Tôi không thực sự thích câu trả lời này vì vậy tôi hy vọng rằng một người khác đến cùng với một lời giải thích tốt hơn về lý do tại sao phương pháp tiếp cận nhóm nút không hoạt động. Nhưng bây giờ, đạo đức của câu chuyện cho các nhà phát triển sử dụng D3: nếu bạn liên tục thêm và sau đó loại bỏ nhiều nút có ID duy nhất (ví dụ: từ các cuộc gọi .ajax lấy các bản ghi ra khỏi db), bạn có thể có nguy cơ bị rò rỉ bộ nhớ.