Chrome 開發工具之 Memory
阿新 • • 發佈:2019-08-12
開發過程中難免會遇到記憶體問題,emmm... 本文主要記錄一下Chrome排查記憶體問題的面板,官網也有,但有些說明和例子跟不上新的版本了,也不夠詳細...
!!! 多圖預警!!!
簡單的記憶體資訊列表
如果只想檢視當前瀏覽器的各個 tab 正在使用的記憶體量,則在 Setting - More Tools - Task Manager 即可。效果如下圖:
那個列表裡的可勾選項,沒看錯,是對於可選的資訊資料列。
那個 End Process 按鈕,沒看錯,選擇一項後,可以在瀏覽器所起的任務列表裡關閉改任務(任務可以是開啟頁面的 tab、Chrome 自身一些專案及擴充套件外掛...為什麼不是按鈕上寫的 process,因為這些任務裡面只有部分是在機器程序列表裡列出存在的,強行嚴格 ~ToT~ )
需要看記憶體的實時變化過程,可以在 Chrome - Performance 面板檢視時間軸上記憶體變化情況,其中會有 `js Heap` 記錄的選項,詳情參考 Chrome 開發工具之 Timeline/Performance
Memory 面板初始
如果想要看更多的記憶體資訊快照,則需要開啟 Chrome 瀏覽器的開發者工具中的 Memory 面板了,下面就簡單介紹一下該面板的使用。
它大概是長這樣:
點選按鈕後,陣列中 push 了新的一項物件
圖(array 那塊列表展開就看不到下面列表了,就沒展開):
附上 Containment 檢視,它的排列稍微有些不同,大致如下:
右中那塊區域顯示的記憶體快照資訊,可以在各個資料上右鍵選擇一些操作( `Reveal in Summary view` ),各個欄位代表資訊如下:
右下那塊區域顯示的是被選中物件的詳細資訊,如上面圖片的內容一樣一樣的...可以在各個資料上右鍵選擇一些操作( `Reveal in Summary view` )。
注意:圖中最最下面那塊最有用,就是搜尋,ctrl/command + f 喚出 ~
最後,根據上面的圖來分析一下上面程式碼產生的效果,根據 js 的型別和引用的關係來分析,變數 _____testArray_____ 在列表中的情況是:
記錄完畢,撒花... &nbs
上面有三個按鈕:
- Heap snapshot - 用以列印堆快照,堆快照檔案顯示頁面的 javascript 物件和相關 DOM 節點之間的記憶體分配
- Allocation instrumentation on timeline - 在時間軸上記錄記憶體資訊,隨著時間變化記錄記憶體資訊。
- Allocation sampling - 記憶體資訊取樣,使用取樣的方法記錄記憶體分配。此配置檔案型別具有最小的效能開銷,可用於長時間執行的操作。它提供了由 javascript 執行堆疊細分的良好近似值分配。
- Summary - 可以顯示按建構函式名稱分組的物件。使用此檢視可以根據按建構函式名稱分組的型別深入瞭解物件(及其記憶體使用),適用於跟蹤 DOM 洩漏。
- Comparison - 可以顯示兩個快照之間的不同。使用此檢視可以比較兩個(或多個)記憶體快照在某個操作前後的差異。檢查已釋放記憶體的變化和參考計數,可以確認是否存在記憶體洩漏及其原因。
- Containment - 此檢視提供了一種物件結構檢視來分析記憶體使用,由頂級物件作為入口。
- Statistic - 記憶體使用餅狀的統計圖。
var _____testArray_____ = [{ value: 'hello' }] function someTodo() { _____testArray_____.push({ value: ':::::::::' }) } document.querySelector('#btn').addEventListener('click', someTodo, false)
入口有:
- DOMWindow - 是被視為 JavaScript 程式碼 "全域性" 物件的物件。
- GC - VM 的垃圾使用的實際 GC 根。GC 根可以由內建物件對映、符號表、VM 執行緒堆疊、編譯快取、控制代碼作用域和全域性控制代碼組成。
- 原生物件 - 是 "推送" 至 JavaScript 虛擬機器內以允許自動化的瀏覽器物件,例如 DOM 節點和 CSS 規則。
右中那塊區域顯示的記憶體快照資訊,可以在各個資料上右鍵選擇一些操作( `Reveal in Summary view` ),各個欄位代表資訊如下:
- Contructor - 表示使用此建構函式建立的所有物件
- Distance - 顯示使用節點最短簡單路徑時距根節點的距離
- Shallow Size - 顯示通過特定建構函式建立的所有物件淺層大小的總和。淺層大小是指物件自身佔用的記憶體大小(一般來說,陣列和字串的淺層大小比較大)
- Retained Size - 顯示同一組物件中最大的保留大小。某個物件刪除後(其依賴項不再可到達)可以釋放的記憶體大小稱為保留大小。
- #New - Comparison 特有 - 新增項
- #Deleted - Comparison 特有 - 刪除項
- #Delta - Comparison 特有 - 增量
- Alloc. Size - Comparison 特有 - 記憶體分配大小
- Freed Size - Comparison 特有 - 釋放大小
- Size Delta - Comparison 特有 - 記憶體增量
右下那塊區域顯示的是被選中物件的詳細資訊,如上面圖片的內容一樣一樣的...可以在各個資料上右鍵選擇一些操作( `Reveal in Summary view` )。
注意:圖中最最下面那塊最有用,就是搜尋,ctrl/command + f 喚出 ~
最後,根據上面的圖來分析一下上面程式碼產生的效果,根據 js 的型別和引用的關係來分析,變數 _____testArray_____ 在列表中的情況是:
- 基礎型別 string 值為 hello ,記憶體標記是 string@353953,這個 string 值存在於 Object @362113 物件上的 value 屬性上;
- Object @362113 在 Object 列表裡,在 Array @356493 的索引 0 位置存在該物件的引用;
- Array @356493 在 Window / @353829 物件上存在引用,屬性名為"___testArray___";
- Window / @353829 是個 Windows 物件,在 Windows 列表裡。
"hello" -> 在(string)列表裡 -> string@353953 -> value in Object @362113 Object -> 在 Object 列表裡 -> [0] in Array @356493 Array -> 在(array)列表裡 -> _____testArray_____ in Window / @353829 Windows -> 在 Windows 列表裡 -> Window / @353829Allocation instrumentation on timeline 看完靜態的快照,再來看看動態的。 程式碼如下:
var _____testArray_____ = [{ value: 'hello' }] var count = 1 function someTodo() { // 每次點選 字串長度都以上一次為基礎增加到5倍,拉大差異突出效果,並且之後在字串頭部加上count值做區分 count *= 5 var str = new Array(count * 10).join(':') _____testArray_____.push({ value: count + str }) } document.querySelector('#btn').addEventListener('click', someTodo, false)選擇 Allocation instrumentation on timeline 點選開始記錄的按鈕,然後得到如圖所示:
每條線的高度與最近分配的物件大小對應,豎線的顏色表示這些物件是否仍然顯示在最終的堆快照中。藍色豎線表示在時間線最後物件仍然顯示,灰色豎線表示物件已在時間線期間分配,但曾對其進行過垃圾回收。(這圖中不是很明顯,放大 devtool 面板後,圖中的藍色線頂部是有部分是灰色的...) 可以選擇時間範圍,檢視該時間範圍內的記憶體變化情況,如上圖 5 次變化的情況分別是:
# 前面的數字代表本次記錄索引,點選了5次 # 0 Shallow Size : 112 Constructor Distance Shallow Size Retained Size - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (array)×9 3 5008 0% 5008 0% (system)×60 3 2416 0% 2640 0% (closure)×1 3 4768 0% 2928 0% Object×3 3 144 0% 768 0% MouseEvent×3 4 112 0% 7200 0% (string)×2 5 96 0% 96 0% (concatenated string)×2 4 64 0% 160 0% Event 5 56 0% 2040 0% UIEvent 5 32 0% 648 0% # 1 (string)×2 5 296 0% 296 0% (concatenated string)×2 4 64 0% 360 0% Object 3 32 0% 392 0% # 2 (string)×2 5 1296 0% 1296 0% (concatenated string)×2 4 64 0% 1360 0% Object 3 32 0% 1392 0% # 3 (string)×2 5 6296 0% 6296 0% (concatenated string)×2 4 64 0% 6360 0% Object 3 32 0% 6392 0% # 4 (string)×2 5 31296 0% 31296 0% (array) 4 80 0% 80 0% (concatenated string)×2 4 64 0% 31360 0% (system) 4 32 0% 32 0% Object 3 32 0% 31392 0%
當勾選 Record allocation stacks 框後,還可以在 Allocation stack 面板裡打印出呼叫堆疊。 如上面程式碼的效果:
Allocation sampling 這個功能根據名稱和說明,不是很看得懂是什麼... 但是,還是通過一些案例給出了效果圖,如下:
根據給出的圖,可以看出這塊的功能應該是:哪些函式影響了記憶體的分配,並且該函式所耗記憶體在記憶體分配中佔比多少。 圖中函式可以直接點選跳轉到函式定義的檔案和位置。
記錄完畢,撒花... &nbs