我刚刚与一位客户会面,他们的Ajax webapp存在严重的内存泄漏问题。因此,我决定创建以下测试用例来演示该问题:
在下面的示例中,我使用了drip / Sieve进行内存分析(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>
每次点击populate list按钮时,会添加10000个li元素(以文本形式表示)。Clearlist调用jQuery empty()方法,应该清空DOM子树并使其符合GC条件。
我在sIEve中运行此案例,并且每次追加新元素时,内存使用量都会增加。即使RAM使用量达到了1.5GB,我仍然从未看到它进行垃圾回收或释放内存。即使我尝试为IE显式调用GC。
这是我在客户端看到的相同症状,他们使用Jquery Ajax获取列表数据而不是我的静态内容。
我是否以错误的方式创建了DOM?有人能告诉我为什么它没有被垃圾回收,我看不到任何其他对DOM元素的引用,也不知道为什么它们不应该被垃圾回收。另一个奇怪的行为是,有时在sIEve中单击empty list(调用jquery empty()方法时),内存使用量甚至会增加?
如果有人有任何建议,我会非常高兴。
更新, 我尝试使用$('#listparent').html("")代替,似乎可以正确释放DOM,在sIEve中已经被释放。我想这是目前最好的解决方案,尽管我无法解释为什么remove()和empty()似乎不起作用。也许它们只适用于静态添加的元素?