成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript 堆內(nèi)存分析新工具 OneHeap

zilu / 2160人閱讀

摘要:關(guān)注于運(yùn)行中的內(nèi)存信息的展示,用可視化的方式還原了,有助于理解內(nèi)存管理。背景運(yùn)行過程中的大部分?jǐn)?shù)據(jù)都保存在堆中,所以性能分析另一個(gè)比較重要的方面是內(nèi)存,也就是堆的分析。上周發(fā)布了工具,可以用來動態(tài)地展示的結(jié)果,分析各種函數(shù)的調(diào)用關(guān)系。

  

OneHeap 關(guān)注于運(yùn)行中的 JavaScript 內(nèi)存信息的展示,用可視化的方式還原了 HeapGraph,有助于理解 v8 內(nèi)存管理。

背景

JavaScript 運(yùn)行過程中的大部分?jǐn)?shù)據(jù)都保存在堆 (Heap) 中,所以 JavaScript 性能分析另一個(gè)比較重要的方面是內(nèi)存,也就是堆的分析。

利用 Chrome Dev Tools 可以生成應(yīng)用程序某個(gè)時(shí)刻的堆快照 (HeapSnapshot),它較完整地記錄了各種對象和引用的情況,堪稱查找內(nèi)存泄露問題的神器。 和 Profile 結(jié)果一樣,快照可以被導(dǎo)出成 .heapsnapshot 文件。

上周發(fā)布了工具 OneProfile , 可以用來動態(tài)地展示 Profile 的結(jié)果,分析各種函數(shù)的調(diào)用關(guān)系。周末我用類似的思路研究了一下 .heapsnapshot 文件,做了這個(gè)網(wǎng)頁小工具,把 Heap Snapshot 用有向圖的方式展現(xiàn)出來。

OneHeap 名字的由來
  

There are only two hard things in Computer Science: cache invalidation and naming things. -- Phil Karlton

目前還沒有時(shí)間想一個(gè)高端、大氣、上檔次的名字,因?yàn)槲夜┞毜墓久?OneAPM ( 省去軟廣1000字,總之做性能監(jiān)控很牛),所以就取名 OneHeap 啦。 它是 Toolkit 里的第二個(gè)。

如何生成 Heap Snapshot 文件 瀏覽器

使用 Chrome 打開 測試頁面 按 F12 打開 Devtools,切換到 Profiles 頁,選擇 Take Heap Snapshot。稍等片刻,在生成的 Snapshot 上點(diǎn)擊右鍵可以導(dǎo)出,文件后綴一般是 .heapsnapshot

Node.JS

如果你是 Node.JS 工程師,可以安裝 heapdump 這個(gè)很有名的模塊。

https://github.com/bnoordhuis/node-heapdump

上面兩種方法都可以生成 .heapsnapshot 文件,這個(gè)是用來測試的 nodejs.heapsnapshot

理解 .heapsnapshot 文件格式

打開測試用的 nodejs.heapsnapshot 文件,這是一個(gè)很大的 JSON 對象:

snapshot 屬性保存了關(guān)于快照的一些基本信息,如 uid,快照名,節(jié)點(diǎn)個(gè)數(shù)等

nodes 保存了是所有節(jié)點(diǎn)的 id,name,大小信息等,對應(yīng) v8 源碼里的 HeapGraphNode

edges 屬性保存了節(jié)點(diǎn)間的映射關(guān)系,對應(yīng) v8 源碼的 HeapGraphEdge

strings 保存了所有的字符串, nodesedges 中不會直接存字符串,而是存了字符串在 strings 中的索引

堆快照其實(shí)是一個(gè)有向圖的數(shù)據(jù)結(jié)構(gòu),但是 .heapsnapshot 文件在存儲的過程中使用了數(shù)組來存儲圖的結(jié)構(gòu),這一設(shè)計(jì)十分巧妙而且減少了所需磁盤空間的大小。

nodes 屬性

nodes 是一個(gè)很長一維的數(shù)組,但是為了閱讀方便,v8 在序列化的時(shí)候會自動加上換行。按照 v8 版本的不同,可能是5個(gè)一行,也可能是6個(gè)一行,如果是 6 個(gè)一行,則多出來的一個(gè) trace_node_id 屬性。

下標(biāo) 屬性 類型
n type number
n+1 name string
n+2 id number
n+3 self_size number
n+4 edge_count number

其中 type 是一個(gè) 0~12 的數(shù)字,目前的 Chrome 只有 0~9 這幾個(gè)屬性,它們對應(yīng)的含義分別是

編號 屬性 說明
0 hidden Hidden node, may be filtered when shown to user.
1 array An array of elements.
2 string A string.
3 object A JS object (except for arrays and strings).
4 code Compiled code.
5 closure Function closure.
6 regexp RegExp.
7 number Number stored in the heap.
8 native Native object (not from V8 heap).
9 synthetic Synthetic object, usualy used for grouping snapshot items together.
10 concatenated string Concatenated string. A pair of pointers to strings.
11 sliced string Sliced string. A fragment of another string.
12 symbol A Symbol (ES6).
edges 屬性

edges 也是一個(gè)一維數(shù)組,長度要比 nodes 大好幾倍,并且相對于 nodes 要復(fù)雜一些:

下標(biāo) 屬性 類型
n type number
n+1 nameorindex stringornumber
n+2 to_node node

其中 type 是一個(gè) 0~6 的數(shù)字:

編號 屬性 說明
0 context A variable from a function context.
1 element An element of an array
2 property A named object property.
3 internal A link that can"t be accessed from JS,thus, its name isn"t a real property name (e.g. parts of a ConsString).
4 hidden A link that is needed for proper sizes calculation, but may be hidden from user.
5 shortcut A link that must not be followed during sizes calculation.
6 weak A weak reference (ignored by the GC).
nodes 和 edges 的對應(yīng)關(guān)系

如果知道某個(gè)節(jié)點(diǎn)的 id,是沒有辦法直接從 edges 中查出和它相鄰的點(diǎn)的,因?yàn)?edges 并不是一個(gè) from-to 的 Hash。想知道從一個(gè)節(jié)點(diǎn)出發(fā) 可到達(dá)那些節(jié)點(diǎn),需要遍歷一次 nodes。

具體做法如下:

在遍歷 nodes 前初始化一個(gè)變量 edge_offset,初始值是0,每遍歷一個(gè)節(jié)點(diǎn)都會改變它的值。

遍歷某個(gè)節(jié)點(diǎn) Nx 的過程中:

從 Nx 出發(fā)的第一條 Edge

edges[ edge_offset ]      是 Edge 的類型
edges[ edge_offset +1 ]   是 Edge 的名稱或下標(biāo)
edges[ edge_offset +2 ]   是 Edge 指向的對象的節(jié)點(diǎn)類型在 `nodes` 里的索引

從 Nx 出發(fā)的第2條 Edge

edges[ edge_offset + 3 ]  
     ............         是下一個(gè) Edge 
edges[ edge_offset + 5 ]

從 Nx 出發(fā),一共有 edge_count 條 Edge

...

3. 每遍歷完一個(gè)節(jié)點(diǎn),就在 edge_offset 上加 3 x edge_count,并回到步驟 2,直到所有節(jié)點(diǎn)都遍歷完

步驟1到3 用偽代碼表示就是:

edge_offset=0

// 遍歷每一個(gè)節(jié)點(diǎn)
for(node in nodes){

  // edges 下標(biāo)從 edge_offset 到 edge_offset + 3 x edge_count    都是 node 可以到達(dá)的點(diǎn)
  edge_offset+= 3 x node.edge_count
}

以上就是 .heapsnapshot 的文件格式定義了,基于這些發(fā)現(xiàn),在結(jié)合一個(gè)前端繪圖的庫,就可以可視化的展示 Heap Snapshot 了。

OneHeap 使用說明

鏈接地址

使用 Chrome 打開: OneHeap

一些有意思的截圖

@1

Node.JS

樸靈老師的《深入淺出Node.JS》有對 Buffer 的詳細(xì)介紹,其中提到 Buffer 是 JavaScript 和 C++ 技術(shù)結(jié)合的典型代表

瀏覽器

很明顯瀏覽器下多了 Window 和 Document 對象,而 Detached DOM tree 正是前端內(nèi)存泄露的高發(fā)地。

Objects

最密集的那部分的中心是 Object 構(gòu)造函數(shù),如果把 Object 和 Array 構(gòu)造函數(shù)隱藏,就變成了下面這樣

MathConstructor

左上角是例如 自然對數(shù)E 這樣的常量,v8源碼

正則表達(dá)式

所有的正則表達(dá)式實(shí)例的 __proto__都指向 RegExp 構(gòu)造函數(shù),同時(shí) RegExp 的 __proto__又指向 Object

Stream

在 Node.JS 中和 Stream 相關(guān)的幾個(gè)類的設(shè)計(jì)和 Java 類似,都使用到裝飾器的設(shè)計(jì)模式,層層嵌套, 例如 v8源碼

參考資料

Heap Profiling

了解 JavaScript 應(yīng)用程序中的內(nèi)存泄漏

關(guān)于

本文相關(guān)的源碼在: https://github.com/wyvernnot/javascriptperformancemeasurement/tree/gh-...;

本文由OneAPM工程師原創(chuàng),想閱讀更多技術(shù)文章,請?jiān)L問OneAPM官方技術(shù)博客。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/85842.html

相關(guān)文章

  • 看完離編寫高性能的JavaScript又近了一步

    摘要:加上內(nèi)部函數(shù)被返回,被其他對象引用,形成了閉包,因此對應(yīng)的變量對象存在于閉包函數(shù)的作用域鏈中。因此訪問次數(shù)越多,費(fèi)用越高,頁面性能就會受到很大影響。盡管還主動執(zhí)行了一次操作,曲線也沒有下降。 副標(biāo)題:常見的JavaScript內(nèi)存泄露 這是關(guān)于JavaScript內(nèi)存泄露相關(guān)的序列文章中一篇。由于時(shí)間有限更新進(jìn)度會有點(diǎn)慢,但會持續(xù)更新的。自己也在學(xué)習(xí)中,難免對某些知識點(diǎn)的理解不是很正確...

    Nekron 評論0 收藏0
  • JavaScript 數(shù)據(jù)結(jié)構(gòu)與算法之美 - 十大經(jīng)典排序算法匯總

    摘要:筆者寫的數(shù)據(jù)結(jié)構(gòu)與算法之美系列用的語言是,旨在入門數(shù)據(jù)結(jié)構(gòu)與算法和方便以后復(fù)習(xí)。這應(yīng)該是目前較為簡單的十大經(jīng)典排序算法的文章講解了吧。比如原本在的前面,而,排序之后,在的后面十大經(jīng)典排序算法冒泡排序思想冒泡排序只會操作相鄰的兩個(gè)數(shù)據(jù)。 showImg(https://segmentfault.com/img/bVbvHet); 1. 前言 算法為王。想學(xué)好前端,先練好內(nèi)功,內(nèi)功不行,就...

    zsy888 評論0 收藏0
  • Node.js內(nèi)存管理和V8垃圾回收機(jī)制

    摘要:垃圾回收內(nèi)存管理實(shí)踐先通過一個(gè)來看看在中進(jìn)行垃圾回收的過程是怎樣的內(nèi)存泄漏識別在環(huán)境里提供了方法用來查看當(dāng)前進(jìn)程內(nèi)存使用情況,單位為字節(jié)中保存的進(jìn)程占用的內(nèi)存部分,包括代碼本身?xiàng)6选? showImg(https://segmentfault.com/img/remote/1460000019894672?w=640&h=426);作者 | 五月君Node.js 技術(shù)棧 | https:...

    JowayYoung 評論0 收藏0
  • 【前端進(jìn)階之路】內(nèi)存基本知識

    摘要:在運(yùn)行腳本時(shí),需要顯示的指定對象。大對象區(qū)每一個(gè)區(qū)域都是由一組內(nèi)存頁構(gòu)成的。這里是唯一擁有執(zhí)行權(quán)限的內(nèi)存區(qū)。換句話說,是該對象被之后所能回收到內(nèi)存的總和。一旦活躍對象已被移出,則在舊的半空間中剩下的任何死亡對象被丟棄。 內(nèi)存管理 本文以V8為背景 對之前的文章進(jìn)行重新編輯,內(nèi)容做了很多的調(diào)整,使其具有邏輯更加緊湊,內(nèi)容更加全面。 1. 基礎(chǔ)概念 1.1 生命周期 不管什么程序語言,內(nèi)存...

    Simon_Zhou 評論0 收藏0
  • 【進(jìn)階1-4期】JavaScript深入之帶你走進(jìn)內(nèi)存機(jī)制

    摘要:引擎對堆內(nèi)存中的對象進(jìn)行分代管理新生代存活周期較短的對象,如臨時(shí)變量字符串等。內(nèi)存泄漏對于持續(xù)運(yùn)行的服務(wù)進(jìn)程,必須及時(shí)釋放不再用到的內(nèi)存。 (關(guān)注福利,關(guān)注本公眾號回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo)) 本周正式開始前端進(jìn)階的第一期,本周的主題是調(diào)用堆棧,今天是第4天。 本計(jì)劃一共28期,每期重點(diǎn)攻克一個(gè)面試重難點(diǎn),如果你還不了解本進(jìn)階計(jì)劃...

    不知名網(wǎng)友 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<