JavaScript 堆內(nèi)存分析新工具 OneHeap
OneHeap 關注于運行中的 JavaScript 內(nèi)存信息的展示,用可視化的方式還原了 HeapGraph,有助于理解 v8 內(nèi)存管理。
JavaScript 運行過程中的大部分數(shù)據(jù)都保存在堆 (Heap) 中,所以 JavaScript 性能分析另一個比較重要的方面是內(nèi)存,也就是堆的分析。
利用 Chrome Dev Tools 可以生成應用程序某個時刻的堆快照 (HeapSnapshot),它較完整地記錄了各種對象和引用的情況,堪稱查找內(nèi)存泄露問題的神器。 和 Profile 結果一樣,快照可以被導出成 .heapsnapshot 文件。
上周發(fā)布了工具 OneProfile , 可以用來動態(tài)地展示 Profile 的結果,分析各種函數(shù)的調(diào)用關系。周末我用類似的思路研究了一下 .heapsnapshot 文件,做了這個網(wǎng)頁小工具,把 Heap Snapshot 用有向圖的方式展現(xiàn)出來。
OneHeap 名字的由來
There are only two hard things in Computer Science: cache invalidation and naming things. -- Phil Karlton
目前還沒有時間想一個高端、大氣、上檔次的名字,因為我供職的公司名叫 OneAPM ( 省去軟廣1000字,總之做性能監(jiān)控很牛),所以就取名 OneHeap 啦。 它是 Toolkit 里的第二個。
如何生成 Heap Snapshot 文件
使用 Chrome 打開 測試頁面 按 F12 打開 Devtools,切換到 Profiles 頁,選擇 Take Heap Snapshot。稍等片刻,在生成的 Snapshot 上點擊右鍵可以導出,文件后綴一般是 .heapsnapshot。
Node.JS
如果你是 Node.JS 工程師,可以安裝 heapdump 這個很有名的模塊。
https://github.com/bnoordhuis/node-heapdump
上面兩種方法都可以生成 .heapsnapshot 文件,這個是用來測試的 nodejs.heapsnapshot
理解 .heapsnapshot 文件格式
打開測試用的 nodejs.heapsnapshot 文件,這是一個很大的 JSON 對象:
snapshot 屬性保存了關于快照的一些基本信息,如 uid,快照名,節(jié)點個數(shù)等
nodes 保存了是所有節(jié)點的 id,name,大小信息等,對應 v8 源碼里的 HeapGraphNode
edges 屬性保存了節(jié)點間的映射關系,對應 v8 源碼的 HeapGraphEdge
strings 保存了所有的字符串, nodes 和 edges 中不會直接存字符串,而是存了字符串在 strings 中的索引
堆快照其實是一個有向圖的數(shù)據(jù)結構,但是 .heapsnapshot 文件在存儲的過程中使用了數(shù)組來存儲圖的結構,這一設計十分巧妙而且減少了所需磁盤空間的大小。
nodes 屬性
nodes 是一個很長一維的數(shù)組,但是為了閱讀方便,v8 在序列化的時候會自動加上換行。按照 v8 版本的不同,可能是5個一行,也可能是6個一行,如果是 6 個一行,則多出來的一個 trace_node_id 屬性。