在測試我們的Javascript庫時,我認爲我們在IE10(v10.0.9200.16519 - Windows 8 64位)Javascript實現setInterval
中發現了嚴重的內存泄漏。解決方法IE10 setInterval內存泄漏
一個簡單的測試案例表明,如果一個變量在作爲參數傳遞的函數的閉包中被捕獲以供後續執行,它似乎沒有資格進行垃圾回收,即瀏覽器似乎仍然持有引用到函數或者至少是閉包變量。
我們的測試用例執行setInterval
功能只有一次,然後沒有代碼被運行了一段時間後,清除間隔定時器,即沒有變量訪問了(據我可以看到沒有全局介紹了在這段代碼中,除了該方法在onload
中運行),但該進程佔用了半個千兆字節的內存(取決於迭代次數)。
有趣的是,如果我們使用setTimeout
方法,而不是(也問題不似乎沒有在IE9存在,和目前版本的Chrome,FF)不會發生這種情況。
該問題可以通過this fiddle查看。
在Windows 8上的IE10的新實例中運行它,並打開任務管理器以查看內存使用情況。它將快速增長到350兆字節,並在腳本執行後停留在那裏。
這是有問題的代碼塊的重要組成部分:
// the function that when called multiple times will cause the leak in IE10
var eatMemory = function() {
var a = null; // the captured closure variable
var intervalId = setInterval(function() {
a = createBigArray(); // call a method that allocates a lot of memory
clearInterval(intervalId); // stop the interval timer
}, 100);
}
(我知道這是很容易解決這個特定一段代碼但是,這不是問題的關鍵 - 這僅僅是最小的。一段代碼,我們想出了能重現問題,真正的代碼實際上捕獲在封閉this
和對象是永遠不會被垃圾收集。)
有沒有在我們的代碼中的bug或者有使用setInterval
其中一種方式一個閉包變量持有對al的引用arge對象,而不會觸發內存泄漏並且不會恢復爲「遞歸」調用?
(我也posted the question on MSDN)
更新:這個問題也存在於IE10在Windows 7上,但如果切換到IE9標準的模式不存在。我將此提交給MS Connect並報告進度。
更新:微軟accepted the issue並報告它被固定在IE11(預覽版) - 我沒有這個確認自己,但
更新: IE 11已經正式發佈(人?)並且我無法使用我的系統(Win 8.1 Pro 64bit)再現該版本的問題。由回落到setTimeout
正如我已經寫了(和評論者建議),這可以被合作周圍(不固定):
你爲什麼要創建一個間隔,然後立即將其清除?這不是破壞目的嗎? – 2013-04-09 15:13:42
@BradM我用一個解釋更新了問題 - 真實的代碼比這更復雜,並不總是無條件地清除間隔。 – Sebastian 2013-04-09 15:18:53
您是否嘗試過不使用匿名函數,而是使用函數引用 - 之後顯式覆蓋此引用? – CBroe 2013-04-09 15:22:00