javascript 內(nèi)存泄漏與 Chrome dev tools

什么是內(nèi)存泄露?

內(nèi)存泄露是指new了一塊內(nèi)存,但無(wú)法被釋放或者被垃圾回收淮逊。new了一個(gè)對(duì)象之后,它申請(qǐng)占用了一塊堆內(nèi)存扶踊,當(dāng)把這個(gè)對(duì)象指針置為null時(shí)或者離開(kāi)作用域?qū)е卤讳N毀泄鹏,那么這塊內(nèi)存沒(méi)有人引用它了在JS里面就會(huì)被自動(dòng)垃圾回收。但是如果這個(gè)對(duì)象指針沒(méi)有被置為null秧耗,且代碼里面沒(méi)辦法再獲取到這個(gè)對(duì)象指針了备籽,就會(huì)導(dǎo)致無(wú)法釋放掉它指向的內(nèi)存,也就是說(shuō)發(fā)生了內(nèi)存泄露分井。

Chrome dev tool 術(shù)語(yǔ)

Shallow size

這是指對(duì)象本身獲得的內(nèi)存大小车猬。

典型的 JavaScript 對(duì)象會(huì)獲得一些保留的內(nèi)存,用于他們的描述以及存儲(chǔ)即時(shí)產(chǎn)生的值尺锚。通常情況下珠闰,只有數(shù)組和字符串才會(huì)有比較明顯的淺層大小。不過(guò)瘫辩,字符串和外部數(shù)組往往在渲染內(nèi)存中有它們自己的主存儲(chǔ)器伏嗜,對(duì) JavaScript 堆只露出一點(diǎn)包裝后的對(duì)象。

渲染內(nèi)存是指所監(jiān)視的頁(yè)面被渲染的過(guò)程中使用的內(nèi)存:原本分配的內(nèi)存 + 該頁(yè)面在 JS 堆中的內(nèi)存 + 所有因?yàn)樵擁?yè)面而導(dǎo)致的 JS 堆中其他對(duì)象的內(nèi)存開(kāi)銷伐厌。然而承绸,即使是一個(gè)小的對(duì)象也可以通過(guò)阻止垃圾回收器自動(dòng)回收其他對(duì)象來(lái)間接保有大量的內(nèi)存。

Retained size

這是指對(duì)象以及其相關(guān)的對(duì)象一起被刪除后所釋放的內(nèi)存大小挣轨,并且 GC roots 無(wú)法到達(dá)該處军熏。

GC roots 是由在從原生代碼的 V8 之外引用 JavaScript 對(duì)象的時(shí)候所創(chuàng)建的句柄(局部或者全局的)構(gòu)成的。這些句柄可以再堆的快照中 GC roots > Handle scope 以及 GC roots > Global handles 中找到刃唐。在沒(méi)有談及瀏覽器實(shí)現(xiàn)的細(xì)節(jié)的情況下,就在本文中說(shuō)明句柄會(huì)令讀者感到困惑界轩,故而關(guān)于句柄的細(xì)節(jié)本文不做講解画饥。事實(shí)上,無(wú)論 GC roots 還是句柄浊猾,都不是你需要擔(dān)心的東西抖甘。

使用 Chrome 任務(wù)管理器實(shí)時(shí)監(jiān)視內(nèi)存使用

使用 Chrome 任務(wù)管理器作為內(nèi)存問(wèn)題調(diào)查的起點(diǎn)。 任務(wù)管理器是一個(gè)實(shí)時(shí)監(jiān)視器葫慎,可以告訴您頁(yè)面當(dāng)前正在使用的內(nèi)存量衔彻。

1薇宠、按 Shift+Esc 或者轉(zhuǎn)到 Chrome 主菜單并選擇 More tools > Task manager,打開(kāi)任務(wù)管理器艰额。


2澄港、右鍵點(diǎn)擊任務(wù)管理器的表格標(biāo)題并啟用 JavaScript memory。



下面兩列可以告訴您與頁(yè)面的內(nèi)存使用有關(guān)的不同信息:

  • Memory 列表示原生內(nèi)存柄沮。DOM 節(jié)點(diǎn)存儲(chǔ)在原生內(nèi)存中回梧。 如果此值正在增大,則說(shuō)明正在創(chuàng)建 DOM 節(jié)點(diǎn)祖搓。
  • JavaScript Memory 列表示 JS 堆狱意。此列包含兩個(gè)值。 您感興趣的值是實(shí)時(shí)數(shù)字(括號(hào)中的數(shù)字)拯欧。 實(shí)時(shí)數(shù)字表示您的頁(yè)面上的可到達(dá)對(duì)象正在使用的內(nèi)存量详囤。 如果此數(shù)字在增大,要么是正在創(chuàng)建新對(duì)象镐作,要么是現(xiàn)有對(duì)象正在增長(zhǎng)藏姐。

使用堆快照發(fā)現(xiàn)已分離 DOM 樹(shù)的內(nèi)存泄漏

只有頁(yè)面的 DOM 樹(shù)或 JavaScript 代碼不再引用 DOM 節(jié)點(diǎn)時(shí),DOM 節(jié)點(diǎn)才會(huì)被作為垃圾進(jìn)行回收滑肉。 如果某個(gè)節(jié)點(diǎn)已從 DOM 樹(shù)移除包各,但某些 JavaScript 仍然引用它,我們稱此節(jié)點(diǎn)為“已分離”靶庙。已分離的 DOM 節(jié)點(diǎn)是內(nèi)存泄漏的常見(jiàn)原因问畅。此部分將教您如何使用 DevTools 的堆分析器確定已分離的節(jié)點(diǎn)。

堆快照是確定已分離節(jié)點(diǎn)的一種方式六荒。顧名思義护姆,堆快照可以為您顯示拍攝快照時(shí)內(nèi)存在您頁(yè)面的 JS 對(duì)象和 DOM 節(jié)點(diǎn)間的分配。

要?jiǎng)?chuàng)建快照掏击,請(qǐng)打開(kāi) DevTools 并轉(zhuǎn)到 Memory面板卵皂,選擇 Heap Snapshot 單選按鈕,然后按 Take Snapshot 按鈕



快照可能需要一些時(shí)間處理和加載砚亭。完成后灯变,請(qǐng)從左側(cè)面板(名稱為 HEAP SNAPSHOTS)中選擇該快照。

在 Class filter 文本框中鍵入 Detached捅膘,搜索已分離的 DOM 樹(shù)添祸。



展開(kāi)三角符號(hào)以調(diào)查分離的樹(shù)。

使用分配時(shí)間線確定 JS 堆內(nèi)存泄漏

分配時(shí)間線是您可以用于跟蹤 JS 堆中內(nèi)存泄漏的另一種工具寻仗。
要顯示分配時(shí)間線刃泌,請(qǐng)考慮使用下面的代碼

var x = [];

function grow() {
  x.push(new Array(1000000).join('x'));
}

document.getElementById('grow').addEventListener('click', grow);

每次按代碼中引用的按鈕時(shí),都會(huì)向 x 數(shù)組添加一個(gè)由 100 萬(wàn)個(gè)字符組成的字符串。

要記錄分配時(shí)間線耙替,請(qǐng)打開(kāi) DevTools亚侠,然后轉(zhuǎn)到 Memory 面板,選擇 Allocation instrumentation on timeline 單選按鈕俗扇,按 Start 按鈕硝烂,執(zhí)行您懷疑導(dǎo)致內(nèi)存泄漏的操作。完成后狐援,按 stop recording 按鈕 钢坦。
記錄時(shí),請(qǐng)注意分配時(shí)間線上是否顯示任何藍(lán)色豎線(如下面的屏幕截圖所示)啥酱。


這些藍(lán)色豎線表示新內(nèi)存分配爹凹。新內(nèi)存分配中可能存在內(nèi)存泄漏。 您可以在豎線上放大镶殷,將 Constructor 窗格篩選為僅顯示在指定時(shí)間范圍內(nèi)分配的對(duì)象禾酱。

展開(kāi)對(duì)象并點(diǎn)擊它的值,可以在 Object 窗格中查看其更多詳情绘趋。

造成內(nèi)存泄露的可能會(huì)有以下幾種情況:

(1)監(jiān)聽(tīng)在window/body等事件沒(méi)有解綁
(2)綁在EventBus的事件沒(méi)有解綁
(3)Vuex的$store watch了之后沒(méi)有unwatch
(4)模塊形成的閉包內(nèi)部變量使用完后沒(méi)有置成null
(5)使用第三方庫(kù)創(chuàng)建颤陶,沒(méi)有調(diào)用正確的銷毀函數(shù)
(6)被遺忘的計(jì)時(shí)器或回調(diào)函數(shù)

參考鏈接

一個(gè)Vue頁(yè)面的內(nèi)存泄露分析
Chrome開(kāi)發(fā)工具 JavaScript 內(nèi)存分析
chrome內(nèi)存泄露(一)、內(nèi)存泄漏分析工具

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末陷遮,一起剝皮案震驚了整個(gè)濱河市滓走,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌帽馋,老刑警劉巖搅方,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異绽族,居然都是意外死亡姨涡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門吧慢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)涛漂,“玉大人,你說(shuō)我怎么就攤上這事检诗⌒僬蹋” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵逢慌,是天一觀的道長(zhǎng)悠轩。 經(jīng)常有香客問(wèn)我,道長(zhǎng)涕癣,這世上最難降的妖魔是什么哗蜈? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮坠韩,結(jié)果婚禮上距潘,老公的妹妹穿的比我還像新娘。我一直安慰自己只搁,他們只是感情好音比,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著氢惋,像睡著了一般洞翩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上焰望,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天骚亿,我揣著相機(jī)與錄音,去河邊找鬼熊赖。 笑死来屠,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的震鹉。 我是一名探鬼主播俱笛,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼传趾!你這毒婦竟也來(lái)了迎膜?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤浆兰,失蹤者是張志新(化名)和其女友劉穎磕仅,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體镊讼,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宽涌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蝶棋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片卸亮。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖玩裙,靈堂內(nèi)的尸體忽然破棺而出兼贸,到底是詐尸還是另有隱情,我是刑警寧澤吃溅,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布溶诞,位于F島的核電站,受9級(jí)特大地震影響决侈,放射性物質(zhì)發(fā)生泄漏螺垢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望枉圃。 院中可真熱鬧功茴,春花似錦、人聲如沸孽亲。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)返劲。三九已至玲昧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間篮绿,已是汗流浹背孵延。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留亲配,地道東北人隙袁。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像弃榨,于是被迫代替她去往敵國(guó)和親菩收。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容