使用堆快照
你可以從正在執行的應用程式中獲取堆快照,並將其載入到 Chrome 開發者工具中,以檢查某些變數或檢視保留大小。你還可以比較多個快照以檢視隨時間的變化。
警告
建立快照時,主執行緒中的所有其他工作都會停止。根據堆內容,這甚至可能需要一分鐘以上。快照是在記憶體中構建的,因此它可能會使堆大小加倍,從而導致記憶體被完全填滿,然後應用程式崩潰。
如果你要在生產環境中進行堆快照,請確保你正在操作的程序崩潰不會影響應用程式的可用性。
操作方法
獲取堆快照
有多種方法可以獲取堆快照:
- 透過檢查器 (inspector),
- 透過外部訊號和命令列標誌,
- 透過在程序內呼叫
writeHeapSnapshot, - 透過檢查器協議。
1. 在檢查器中使用記憶體分析
適用於所有正在積極維護的 Node.js 版本
使用 --inspect 標誌執行 node 並開啟檢查器。 ![]()
獲取堆快照的最簡單方法是連線檢查器到本地執行的程序。然後轉到“記憶體”選項卡並獲取堆快照。
![]()
2. 使用 --heapsnapshot-signal 標誌
適用於 v12.0.0 或更高版本
你可以透過一個命令列標誌啟動 node,使其能夠響應訊號來建立堆快照。
$ node --heapsnapshot-signal=SIGUSR2 index.js
有關詳細資訊,請參閱 heapsnapshot-signal 標誌的最新文件。
3. 使用 writeHeapSnapshot 函式
適用於 v11.13.0 或更高版本。在舊版本中可使用 heapdump 包
如果你需要從一個正在執行的程序(例如在伺服器上執行的應用程式)獲取快照,你可以透過以下方式實現:
('v8').();
檢視 writeHeapSnapshot 文件瞭解檔名選項。
你需要一種在不停止程序的情況下呼叫它的方法,因此建議在 HTTP 處理程式中或作為對作業系統訊號的響應來呼叫它。注意不要暴露觸發快照的 HTTP 端點。不應讓任何其他人能夠訪問它。
對於 v11.13.0 之前的 Node.js 版本,你可以使用 heapdump 包。
4. 使用檢查器協議觸發堆快照
檢查器協議可用於從程序外部觸發堆快照。
使用該 API 並不需要執行 Chromium 的實際檢查器。
這是一個在 bash 中使用 websocat 和 jq 的快照觸發示例
#!/bin/bash
set -e
kill -USR1 "$1"
rm -f fifo out
mkfifo ./fifo
websocat -B 10000000000 "$(curl -s https://:9229/json | jq -r '.[0].webSocketDebuggerUrl')" < ./fifo > ./out &
exec 3>./fifo
echo '{"method": "HeapProfiler.enable", "id": 1}' > ./fifo
echo '{"method": "HeapProfiler.takeHeapSnapshot", "id": 2}' > ./fifo
while jq -e "[.id != 2, .result != {}] | all" < <(tail -n 1 ./out); do
sleep 1s
echo "Capturing Heap Snapshot..."
done
echo -n "" > ./out.heapsnapshot
while read -r line; do
f="$(echo "$line" | jq -r '.params.chunk')"
echo -n "$f" >> out.heapsnapshot
i=$((i+1))
done < <(cat out | tail -n +2 | head -n -1)
exec 3>&-
這是一個可與檢查器協議一起使用的記憶體分析工具的不完全列表
如何使用堆快照查詢記憶體洩漏
你可以透過比較兩個快照來發現記憶體洩漏。重要的是要確保快照差異不包含不必要的資訊。以下步驟應該可以產生乾淨的快照差異。
- 讓程序載入所有原始檔並完成引導。這最多需要幾秒鐘。
- 開始使用你懷疑洩漏記憶體的功能。它可能會進行一些初始分配,這些分配不是洩漏的部分。
- 獲取一個堆快照。
- 繼續使用該功能一段時間,最好在此期間不要執行任何其他程式。
- 獲取另一個堆快照。兩者之間的差異應該主要包含洩漏的內容。
- 開啟 Chromium/Chrome 開發者工具並轉到“記憶體”選項卡
- 首先載入較舊的快照檔案,然後再載入較新的檔案。

- 選擇較新的快照,並在頂部的下拉選單中將模式從“摘要”切換到“比較”。

- 查詢大的正增量,並在底部面板中探索導致它們的原因引用。
你可以透過這個堆快照練習來練習捕獲堆快照和查詢記憶體洩漏。