4種視圖
- Summary 視圖。該視圖適合用於檢查DOM節點泄露。按照構造函數名字分類的視圖。查看每一個構造函數有多少個對象。
不能寫匿名函數和匿名閉包:用於歸因,假設應該函數內存泄露,可是又不知道名字,無疑加大難度html
使用技巧:再Class Filter中,搜索Detached
能夠查看是否有分離的DOM。也能夠搜索想要查看的構造器的名稱react
而後看retainers窗口,第一行通常是引用該對象的元素。能夠經過distance列來看,通常會比Detached
的節點上一層git
-
Comparison 視圖。也是根據構造函數分類,比較兩個快照。好比react的
FiberNode
增長多少,刪除多少github -
Containment 視圖。自上而下查看對象引用鏈。web
-
Dominators 視圖 爲何找不到
Dominators view
? 注意: Chrome Canary 版本 的DevTools中的Settings > experiments > Show advanced heap snapshot properties 開啓,重啓DevTools生效 不過根據這個提示也沒找到chrome
概念
-
Distance:GC ROOTS 倒該對象的距離。從1開始antd
-
Shallow size : 對象自身大小閉包
-
Retained size:對象所引用的全部對象的大小。也就是假設該對象去除後,將會釋放這麼多內存chrome-devtools
-
Detached: 已經與HTML分離,可是Javascript仍然保留引用。說明沒有清除乾淨,存在內存泄露。說一些例子函數
- html已被移除。可是Javascript仍然監聽着事件,說明存在內存泄露
document.createElement
,Javascript端一直保存着
-
黃色背景對象:已經分離的DOM節點(Detached節點),可是仍被Javascript端引用着。可能存在DOM節點泄露
-
紅色背景對象:已經分離的DOM節點(Detached節點),可是被黃色背景的DOM引用着。可能存在DOM節點泄露
注意: 在React中由於組件會切換顯示/隱藏。因此會保留(retain)原來的DOM對象,也就是會存在Detached
的DOM是正常的;當切換導其餘頁面時就會被GC;只有不能被GC的Detached
DOM纔算是內存泄露
Allocation Timeline 解決JS堆內存泄露
藍色線是申請內存。若是很高能夠排查
Allocation Samping 查看函數內存申請
遇到的坑
Chrome password控件不會釋放內存
react使用 input password控件不會釋放內存,子組件不釋放,父組件頁面就不會釋放。 使用antd pro
的Password
組件,通過來回切換路由(頁面)後,原先的頁面依然存在(Summary頁面查詢名字),在summary的頁面中會有不少個對象,而且只有一個是有distance
,其餘都是橫槓-
。將password
換成普通的input
就會正常被GC掉。最後有使用者發現其實這是chrome的BUG.
chrome console.log 會內存泄露
背景:有一個很大的表格react組件,由於調試用了console.log輸出props
屬性。而後切換路由,發現出現這個頁面一直沒有被GC回收!!而且distance仍是斜槓
最後去掉console的輸出,GC正常。由於console.log會保持輸出對象的引用不被GC回收,不然回收了怎麼看內容調試呢。所以生產環境要去掉不必的console
例子
let leakObjects = []; function MyObject() {} for (let i = 0; i < 100000; ++i) { leakObjects.push(new MyObject()); } console.log(leakObjects); // chrome devtool > memory > heap snapshot > summary > class filter 輸入 MyObject // 即使不引用也是不會被GC回收,出現內存泄露 leakObjects = null;
issues: Password input type causes memory leak #14962
Issue 967438: Memory leak with input type=password
其實火狐的工具也是很不錯的 https://developer.mozilla.org/zh-CN/docs/Tools/Memory/Dominators_view