2013-03-09 34 views
3

我有一個簡單的html/javascript代碼,它會創建一些DOM然後刪除它們。這個簡單的js代碼是否有內存泄漏?

<!DOCTYPE html> 
<html> 

    <head lang="en"> 
    <meta charset="utf-8"> 
    <title>Custom Plunker</title> 
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> 
    </head> 

    <body> 
    <button onclick="create()"> Create </button> 
    <button onclick="clearContainer()"> Clear </button> 

    <div id="container"></div> 

    </body> 

</html> 

<script> 
    function create() { 
    var c = $("#container"); 
    for(var i = 0;i<10000; i++){ 
    c.append("<li>Hellosd fssd f df sdf f f wef ewf we fwe f wef ewf wef ew few f ewf wf ewf wef </li>"); 
    } 
    } 

    function clearContainer() { 
    var c = $("#container"); 
    c.empty(); 
    } 
</script> 

將會有一個Create按鈕和Clear按鈕。當我點擊創建按鈕時,它會將10000 li元素附加到容器div上,當我點擊清除按鈕時,它將刪除它們。

當我在chrome上試用它時,chrome進程的初始內存使用量約爲30M,在我多次點擊創建按鈕後增長到70M,當我點擊清除按鈕時,它變爲50M。它比最初的要多20M。

然後我在IE8上試用它,IE進程初始內存使用量約30M,點擊創建按鈕一次後增長到100M以上,當我點擊清除按鈕時,它變爲80M。它比最初的多50M。

代碼是否有內存泄漏?如何解決它?

+0

你莫名其妙地測量實際數據使用或者是你測量(更可能)的內存保留,這會比實際使用的數據嗎? – kainaw 2013-03-09 15:41:44

+0

這裏有一個[小提琴](http://jsfiddle.net/3SX59/)看到它在行動。 – insertusernamehere 2013-03-09 15:43:08

回答

7

代碼是否有內存泄漏?

不。瀏覽器只是保留一些內存,以防他們需要重用它,和/或尚未(垃圾)收集不再被引用的對象。因爲您已經發布了所有對列表項元素的引用(通過jQuery的empty調用),所以實際上讓它們放到瀏覽器上。

當然,這個答案假設你調用的jQuery函數沒有錯誤導致內存泄漏(尤其是創建li元素的那個)。這可能是一個合理的假設,儘管當然,即使是一個備受尊敬的圖書館也會偶爾出現錯誤。如果jQuery的一個常用函數(包括元素構造)在給定版本中存在大量內存泄漏,那麼考慮到使用該庫和參與的團隊的人數,可能會在合理的時間內找到,報告並修復它們它。

而且我們也假設有在瀏覽器的處理的DOM操作導致內存泄漏,這是一個更一定假設沒有錯誤。 (歷史上,瀏覽器]無論味】有過各種各樣的問題,內存泄漏,我不認爲任何瀏覽器已經免疫。)

但有在代碼沒有泄漏,如果你明白了嗎。

+0

你確定嗎?我測試了OP的代碼,並且在每次創建/清除佔用的內存後,重要的是大約5到10 MB。 – 2013-03-09 15:46:54

+0

@dystroy:正如你可以只看該代碼。 OP沒有保留對'li'元素的任何引用,所以OP的代碼不是內存泄漏的原因。正如我所說的,它總是可能有一個在jQuery的功能OP呼喚之一,但它更可能只是記憶流失。 – 2013-03-09 15:48:49

+0

在OS X上的Firefox 19「保持」像30MB的第一個*創建/清除*之後每個新一輪之後回落到這一數額。 – insertusernamehere 2013-03-09 15:50:19

4

通過對鉻/ Linux的測試,我可靠地重現您泄漏:每個創建/清除循環,使內存5MB增長到10 MB,並將此內存似乎沒有被釋放。

我注意到,有可能通過稍微改變了明確的功能替換父元素,而不是清空,以避免泄漏:

function clearContainer() { 
    var c = $("#container"); 
    c.remove(); 
    $('<ul id="container"></ul>').appendTo(document.body); 
    } 

有了這個代碼,內存回來以後每次在同一水平創建/清除週期。

我不認爲這個問題是在jQuery的,但更多的可能是在瀏覽器的DOM對象作爲火狐似乎並不有同樣的問題。


編輯

通過自動化測試來進一步推動它,我可以看到內存終於下降(我榮登約150 MB的選項卡,然後可以回來到70 MB)。內存管理的方式顯然是貪婪的,但沒有真正的內存泄漏。由於內存消耗可以如此不同,我建議你刪除的父元素,而不是將其清除,但這不會阻止任何崩潰的內存崩潰似乎不太可能。

+0

+1爲努力和變化。 *「...並且這個記憶永遠不會被釋放。」*你等了多久/你試圖看到這個**從未**被釋放了什麼?你有沒有堅持下去,直到有東西墜毀?這是「內存泄漏」的黃金標準(你需要做的事情很多,將它報告爲Chromium中的錯誤)。 (我並不是說這不是一個有趣的結果,只是它不一定是* leak *,而且它顯然不是* OP的*代碼中的泄漏。) – 2013-03-09 15:57:43

+0

@TJCrowder在我上次測試後內存沒有改變,5分鐘前。它仍然在136 MB,而我的其他清理功能的內存立即釋放。 – 2013-03-09 16:00:31

+0

@消歧:五分鐘不是「從不」。再次,你必須推動它,直到有什麼東西打破來調用泄漏。否則,你只是不知道GC在內部做了什麼。 GC是***複雜***。 – 2013-03-09 16:01:14