使用堆疊快照
您可以從運行中的應用程式中拍攝一個堆疊快照,然後將其加載到Chrome 開發人員工具中,以檢查特定變數或檢查保留器大小。您還可以比較多個快照,以查看隨時間的變化。
警告
在創建快照時,您的主線程中的所有其他工作都將停止。根據堆疊內容,這甚至可能需要超過一分鐘的時間。快照是在內存中構建的,因此它可能會使堆大小加倍,導致整個內存填滿,然後使應用程式崩潰。
如果你要在生產環境中進行堆快照,請確保你所從中取得的進程能夠在不影響應用程序可用性的情況下崩潰。
操作步驟
獲取堆快照
有多種方法可以獲取堆快照
- 透過檢查器,
- 透過外部信號和命令行標誌,
- 通過進程中的
writeHeapSnapshot
調用, - 通過檢查器協議。
1. 在檢查器中使用記憶體分析
適用於所有活躍維護的 Node.js 版本
以--inspect
旗標運行node並開啟檢查器。
取得堆疊快照的最簡單方法是將檢查器連接到您本地運行的進程。然後轉至記憶體標籤並拍攝堆疊快照。
2. 使用--heapsnapshot-signal
旗標
適用於 v12.0.0 或更新版本
您可以使用命令行標誌啟動節點,啟用對信號的反應以創建堆快照。
$ node --heapsnapshot-signal=SIGUSR2 index.js
詳情請參閱 heapsnapshot-signal 標誌 的最新文檔。
3. 使用 writeHeapSnapshot
函數
適用於 v11.13.0 或更新版本,可以使用 heapdump 套件 在舊版本中使用
如果您需要從運行中的進程(例如在服務器上運行的應用程序)獲取快照,可以實現以下方式獲取
require('v8').writeHeapSnapshot();
查看 writeHeapSnapshot
文檔 以獲取文件名選項。
您需要一種方法來在不停止進程的情況下調用它,因此建議在 HTTP 處理程序中調用它,或者作為操作系統信號的反應。請注意不要暴露觸發快照的 HTTP 端點。其他任何人都不應該能夠訪問它。
對於 Node.js 版本 v11.13.0 之前的版本,您可以使用 heapdump 套件。
4. 使用檢查器協議觸發堆快照
檢查員協定可用於從進程外觸發堆快照。
不需要從Chromium運行實際的檢查員來使用API。
這是一個bash中的示例快照觸發,使用websocat
和jq
#!/bin/bash
set -e
kill -USR1 "$1"
rm -f fifo out
mkfifo ./fifo
websocat -B 10000000000 "$(curl -s http://localhost: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開發者工具並轉到記憶體標籤
- 首先加載舊的快照文件,然後加載新的快照文件。
- 在上方的下拉式選單中選擇較新的快照,並將模式從摘要切換到比較模式。
- 尋找大型正數差異,並在底部面板中探索引起它們的參考資料。
您可以使用這個堆快照練習來練習捕獲堆快照並尋找內存洩漏。