2010-11-12 69 views
6

刚刚遇到一位在其Ajax webapp中存在大量内存泄漏问题的客户。所以决定创建以下测试用例来演示该问题:使用jquery append()添加DOM元素似乎泄漏内存?

我在下面 的例子(http://home.orange.nl/jsrosman/)

所使用滴/筛为内存分析情况很简单:我有以下javascript:

<html> 
    <head>  
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js"> 
</script>  
</head>  
<script type="text/javascript"> 

    var lihtml = "<li class='green'>this is a test text</li>"; 

    function populatelist() { 
     for (var i = 0; i < 10000; i++) { 
      $('#listparent').append(lihtml); 
     }  
    }  

    function clearlist() { 
     $('#listparent').empty(); 
     if (typeof (CollectGarbage) == "function") { 
      alert('gc'); 
      CollectGarbage(); 
     }  
    } 


    /* Alternative clearlist with Remove instead of Empty(), still leaks */ 
    function clearlist() { 
     /* test remove the parent itself instead of empty below */ 
     $('#listparent').remove(); 
     $('body').append("<ul id='listparent'>");   
     //$('#listparent').empty(); 
     if (typeof (CollectGarbage) == "function") { 
      alert('gc'); 
      CollectGarbage(); 
     } 
    } 

    /* Edit!, this is the most effective way to release memory so far */ 
    function clearlist() { 
    $('#listparent').html(""); 
    if (typeof (CollectGarbage) == "function") { 
     alert('gc'); 
     CollectGarbage(); 
    } 
} 
</html> 
</script> 

<body> 
    <button onclick="javascript:populatelist()">Populate list</button> 
    <button onclick="javascript:clearlist()">Clear list</button> 
    <ul id="listparent"> 
     <li>kjjk</li> 
    </ul>  
</body> 

</html> 

每个单击填充列表后都会附加10000个li元素(表示为文本)。 Clearlist调用jquery empty(),它应该清除DOM子树并使其符合GC条件。

所以我运行这个案例在sIEve和每次我追加新元素的内存使用增加,我从来没有见过它垃圾收集或释放内存。甚至当RAM使用量达到1.5GB时,即使我尝试为IE显式调用GC。

这与我在使用Jquery Ajax获取List数据而不是我的静态内容obv的客户中看到的相同。

我是否以错误的方式创建DOM?有人可以告诉我为什么它不是垃圾收集,我看不到任何其他DOM元素的引用,为什么他们不应该被垃圾收集。另一个奇怪的行为是,当我单击空列表(当调用jquery empty()方法时),有时在sIEve内存中的使用甚至会增加?

如果有人输入我会非常高兴。

更新,我尝试使用$('#listparent')。html(“”),而不是似乎正确释放DOM,至少它是在sIEve中释放。我想这是迄今为止最好的解决方案,尽管我没有解释为什么remove()和empty()似乎不起作用。也许他们只适用于静态添加元素?

+0

只是好奇,你在多个浏览器尝试这种最有效的方法是什么? – Prescott 2010-11-12 12:30:31

+0

没有sIEve只能在IE中使用,还没有试过FFX,主要是因为IE是本系统中用户唯一使用过的浏览器。 – user408346 2010-11-12 12:55:23

+0

其实$('#listparent')。HTML( “”);比empty()和remove()好得多,似乎释放整个DOM。我很无语 – user408346 2010-11-12 12:55:55

回答

1

是的,你可以使一个巨大的进步做smthg喜欢尽可能少所以

var lihtml = "<li class='green'>this is a test text</li>", 
    listring = ""; 

function populatelist() { 
     for (var i = 0; i < 10000; i++) { 
      listring += lihtml; 
     }  

     $('#listparent').append(listring); 

    }  
... 

限制访问DOM。

不同之处在于,您制作1个单一附加符而不是10,000个附加符号。你总是需要避免DOM周期内的操作

编辑: 而不是空()你的ul你有没有尝试删除()ul然后突然重新创建它?

+0

这是一个很好的建议,我试了一下,问题仍然存在,但它仍然漏气,empty()似乎没有释放DOM。认真开始对jquery失去信心。 – user408346 2010-11-12 12:19:31

+0

我编辑了我的答案 – 2010-11-12 12:23:11

+1

我试过remove(),它仍然泄漏,但可能略少于empty(),这似乎增加内存而不是释放。真奇怪的是$('#listparent')。html(“”);做的伎俩,并释放整个DOM和RAM内存?!? – user408346 2010-11-12 12:47:07

1

我建议追加到HTML字符串,然后将其添加到DOM:

function populatelist() { 
    for (var i = 0; i < 10000; i++) { 
     //$('#listparent').append(lihtml); 
     lihtml += "<li class='green'>this is a test text</li>"; 
    }  
}  
populateList(); 
$('#listparent').append(lihtml); 
+0

和下面一样,建议不错,但泄漏仍然存在。 – user408346 2010-11-12 12:20:14

0
$('#listparent').html(""); 

作品既没有空()或remove()一样。我希望我知道为什么。我想这是一个解决方案。

/*这是为了释放内存到目前为止*/

function clearlist() { 
    $('#listparent').html(""); 
    if (typeof (CollectGarbage) == "function") { 
     alert('gc'); 
     CollectGarbage(); 
    }