如何用 Chrome 解決內(nèi)存泄漏
簡(jiǎn)介
引用自 Google 的描述:
頁(yè)面的性能隨著時(shí)間的延長(zhǎng)越來(lái)越差。 這可能是內(nèi)存泄漏的癥狀。 內(nèi)存泄漏是指,頁(yè)面中的錯(cuò)誤導(dǎo)致頁(yè)面隨著時(shí)間的延長(zhǎng)使用的內(nèi)存越來(lái)越多。
頁(yè)面的性能一直很糟糕。 這可能是內(nèi)存膨脹的癥狀。 內(nèi)存膨脹是指,頁(yè)面為達(dá)到最佳速度而使用的內(nèi)存比本應(yīng)使用的內(nèi)存多。
頁(yè)面出現(xiàn)延遲或者經(jīng)常暫停。 這可能是頻繁垃圾回收的癥狀。 垃圾回收是指瀏覽器收回內(nèi)存。 瀏覽器決定何時(shí)進(jìn)行垃圾回收。 回收期間,所有腳本執(zhí)行都將暫停。因此,如果瀏覽器經(jīng)常進(jìn)行垃圾回收,腳本執(zhí)行就會(huì)被頻繁暫停。
舉個(gè)官網(wǎng)的例子
有以下代碼會(huì)導(dǎo)致內(nèi)存泄漏問(wèn)題
loop.js 代碼
var x = [];
function grow() {
x.push(new Array(1000000).join('x'));
}
document.getElementById('grow').addEventListener('click', grow);
html 代碼
<!DOCTYPE html>
<html>
<head>
<title>memory</title>
</head>
<body>
<p>hello,world</p>
<button id="grow">grow</button>
<script src="loop.js"></script>
</body>
</html>
如何解決
有以下兩個(gè)步驟:
- 檢測(cè)網(wǎng)頁(yè)
- 找出內(nèi)存泄漏的代碼
- 代碼修改
先說(shuō)第一部分:如何檢測(cè)
檢測(cè)
用 Chrome 開(kāi)發(fā)工具進(jìn)行檢測(cè),
- 在 Chrome 的
開(kāi)發(fā)者工具上打開(kāi) Performance 面板。 - 點(diǎn)擊 Memory 復(fù)選框。
- 按紅色那個(gè) Record 按鈕,進(jìn)行記錄
上圖有兩個(gè)地方需要關(guān)注的,就是下面藍(lán)色的線。藍(lán)色的線的起點(diǎn)不斷增高,意味著有部分內(nèi)存沒(méi)有完全的回收釋放掉,也就是說(shuō)意味著頁(yè)面會(huì)不斷地占越來(lái)越多的內(nèi)存。直至最后 Chrome 奔潰!
接著揪出元兇出來(lái)
如何找出
打開(kāi)預(yù)覽圖,然后找一找,在藍(lán)色線增高的點(diǎn)那里,我們?cè)诰W(wǎng)頁(yè)執(zhí)行了什么的操作。
上圖可看出,點(diǎn)擊了按鈕 grow ,這時(shí)可以直接去 grow 觸發(fā)代碼去觀察的了。
如果還不是很確定的話,可以記錄分配時(shí)間線:
- 打開(kāi)開(kāi)發(fā)者工具
- 然后轉(zhuǎn)到
Memory面板,選擇Record Allocation Timeline單選按鈕按Start按鈕,執(zhí)行您懷疑導(dǎo)致內(nèi)存泄漏的操作。完成后 - 按
Stop recording按鈕
選中增高的藍(lán)色線,下面在 Constructor 里看到最高的 string ,點(diǎn)擊后,看下面。會(huì)觀察到原來(lái)是代碼中的 x 變量沒(méi)有被釋放。
修改代碼
我們看到 grow() 的代碼如下:
var x = [];
function grow() {
x.push(new Array(1000000).join('x'));
}
document.getElementById('grow').addEventListener('click', grow);
grow 執(zhí)行的時(shí)候,會(huì)向 x 插入數(shù)據(jù),而 x 這個(gè)變量則是一個(gè)全局變量(實(shí)際可以說(shuō)是 Window對(duì)象下的屬性),而 x 這個(gè)變量沒(méi)有釋放,就導(dǎo)致不停地增加下去了。
我們來(lái)試一種避免內(nèi)存泄漏的寫(xiě)法,避免使用全局變量。將變量寫(xiě)在函數(shù)里面,當(dāng)函數(shù)執(zhí)行完的時(shí)候 x 變量會(huì)釋放
function grow() {
var x = [];
x.push(new Array(1000000).join('x'));
}
其它的方式:參考下面這篇文吧:
參考
這篇文大部分都引用 Google 的這篇文, 部分內(nèi)容做出了修改