使用堆快照
您可以从正在运行的应用程序中获取堆快照,并将其加载到 Chrome 开发者工具 中以检查某些变量或检查保留大小。您还可以比较多个快照以查看随时间的差异。
警告
创建快照时,主线程中的所有其他工作都会停止。根据堆内容,甚至可能需要超过一分钟。快照是在内存中构建的,因此它可以使堆大小翻倍,从而导致内存填满并最终导致应用程序崩溃。
如果要在生产环境中获取堆快照,请确保您从中获取快照的进程可以在不影响应用程序可用性的情况下崩溃。
操作方法
获取堆快照
有多种方法可以获取堆快照
- 通过检查器,
- 通过外部信号和命令行标志,
- 通过进程中的
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 包在旧版本中使用
如果您需要从正在运行的进程(例如在服务器上运行的应用程序)获取快照,您可以使用以下方法实现获取快照:
require('v8').writeHeapSnapshot();
查看writeHeapSnapshot
文档以获取文件名选项。
您需要有一种在不停止进程的情况下调用它的方法,因此建议在 HTTP 处理程序中或作为对操作系统信号的反应来调用它。注意不要公开触发快照的 HTTP 端点。任何人都不能访问它。
对于 v11.13.0 之前的 Node.js 版本,您可以使用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 开发者工具并转到“内存”选项卡
- 首先加载较旧的快照文件,然后加载较新的快照文件。
- 选择较新的快照,并在顶部的下拉菜单中将模式从摘要切换到比较。
- 查找较大的正增量,并在底部面板中探索导致这些增量的引用。
您可以使用此堆快照练习练习捕获堆快照和查找内存泄漏。