【问题标题】:Chrome leaks memory when simply adding and removing SVG elements简单地添加和删除 SVG 元素时,Chrome 会泄漏内存
【发布时间】:2013-01-25 09:43:29
【问题描述】:

继续这个问题:Task manager shows memory leak, but Heap snapshot doesn't

我设法创建了一个非常简单的示例来说明这种泄漏,这里是完整的源代码:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>svg test</title>



        <script type="text/javascript">

            var svg;
            var interval;
            var svg;

            window.onload = function(){
                createSVG();
                start();
            }

            function start(){
                interval = setInterval(createElements, 100);                
            }

            function createSVG(){

                var div = document.getElementById("svgdiv");
                div.innerHTML = "";

                svg = createSvgElement("svg");
                svg.style.position = "absolute";
                svg.style.width = "600px";
                svg.style.height = "500px";
                svg.setAttribute("version", "1.1");
                div.appendChild(svg);
                createElements();               
            }


            function createElements(){

                removeElements();

                for(var i = 0; i < 500; i++){
                    var element = createSvgElement("circle");
                    element.setAttribute("r", Math.random() * 10);
                    var transform = "translate(" + Math.round(Math.random() * 600) + "," + Math.round(Math.random() * 500) + ")";
                    element.setAttribute("transform", transform);
                    element.setAttribute("fill", "#CC0000");
                    svg.appendChild(element);
                }
            }

            function removeElements(){
                while(svg.hasChildNodes() ){
                    svg.removeChild(svg.lastChild);
                }               
            }


            function createSvgElement (name) {
                return document.createElementNS("http://www.w3.org/2000/svg", name);
            }

            function stop(){
                clearInterval(interval)
            }


        </script>
    </head>
    <body style="background-color:#FFFFFF">
        <div id="svgdiv" style="width:600px; height:500px;"></div>
        <input type="button" value="start" onclick="start()">
        <input type="button" value="stop" onclick="stop()">
    </body>
    </html>

如果我运行这个脚本,Chrome 会一直占用内存,直到崩溃。其他浏览器没有。我没有一个一个地删除孩子,我还尝试通过设置innerHTML=""来快速清除它,但它是一样的。

我启用了 Chrome 的一项实验性功能,它显示了所使用的内存类型。 “页面结构”内存增加了一点(但是 HTML 保持不变,并且没有分离的 DOM 对象),但大部分内存都在“其他”部分。

如果我停止脚本并强制 GC 完成它的工作,内存只会减少几千字节。但是,如果我等待一两分钟,内存几乎会被清理到初始水平。我知道我的脚本非常紧张,但是如果我仅每 1 或 2 秒运行一次它也会发生这种情况 - 我认为这足以让 GC 完成它的工作。而且我知道 GC 正在工作,因为释放了其他类型的内存。这可能是Chrome错误吗?也许我应该在删除元素之前做点什么?

【问题讨论】:

标签: javascript memory-leaks svg


【解决方案1】:

我设法减慢它的速度,但它仍在泄漏。我还使用没有泄漏的 Raphael.js 重新创建了测试。但是当我测试时,我发现它是在附加圆圈的时候。所以拉斐尔一定是在做些什么来阻止它在那个时候泄漏。

【讨论】:

  • 尝试注释掉element.setAttribute("fill", "#CC0000");。我注意到使用的内存大幅减少,实际上可以被收集。
  • 嗯,但不应该是这样的。我经常使用 setAttribute 来设置 svg 元素的所有属性。
  • 只有在改变元素颜色时才会出现。
  • 有趣的是,在某些情况下,setAttribute 实际上是不泄漏的变体(这可能是 Raphael.js 没有显示相同问题的原因)。我发现使用 setAttribute(null, "transform", "transform(0,0") 的 Chrome 31 确实 not 泄漏内存,但是通过 Javascript API (element.transform.baseVal.appendItem(...)) 执行相同操作会阻止内存被回收。事实上,只要你这样做了var a= element.transform.baseVal;,该元素就再也不会被垃圾回收了。
【解决方案2】:

不确定是否会有很大帮助,但如果您只定义一次“var svg”, 那么内存消耗(在任务管理器中)并没有那么快上升 并且 stop() 函数在那之后也可以工作

【讨论】:

  • svg 只定义一次。 element 每次都定义了,但它是一个新的对象,所以我觉得还可以。
【解决方案3】:
猜你喜欢
  • 1970-01-01
  • 2015-11-03
  • 2018-06-28
  • 1970-01-01
  • 2012-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-09
  • 2021-01-23
相关资源
最近更新 更多