Node.js 异步模型让性能定位比传统语言更具挑战:事件循环阻塞、Promise 链等待、内存泄漏都需要专门工具链。clinic.js 是最易用的一站式诊断套件。
火焰图:从宽度看耗时
火焰图每一格代表一个函数栈帧,宽度代表占用 CPU 的采样数。平而宽的顶层栈帧就是热点函数;向上生长的尖刺通常是深层递归或同步 IO;找"平顶"最值得优化。
#!/usr/bin/env bash
set -euo pipefail
# 1. 安装工具链
# npm i -g clinic 0x autocannon
# 2. Clinic Doctor: 一键综合体检 (自动压测20s)
# clinic doctor --on-port 'autocannon -c 50 -d 20 http://localhost:$PORT/api/search?q=test' -- node dist/server.js
# 3. 火焰图定位 CPU 热点(0x 工具)
# 0x -- node dist/server.js & sleep 2
# autocannon -c 80 -d 15 http://localhost:3000/api/heavy
# Ctrl+C → flamegraph.html
# 4. Clinic Bubbleprof: 异步延迟分析(Promise/IO等待链条)
# clinic bubbleprof --on-port 'autocannon -c 30 -d 15 http://localhost:$PORT/api/upload' -- node dist/server.js
# 5. Clinic Heapprofiler: 堆内存泄漏(300s采样对比快照)
# clinic heapprofiler --sample-interval 1000 --on-port 'autocannon -c 40 -d 300 http://localhost:$PORT/api/cart' -- node dist/server.js
# 6. V8 底层采样(无侵入生产可用)
NODE_ENV=production node --prof dist/server.js &
SPID=$!; sleep 3
autocannon -c 100 -d 30 http://localhost:3000/api/heavy
kill -INT $SPID
# node --prof-process isolate-0x*-v8.log > processed.txt
# 查看 [Bottom up (heavy) profile] 部分
Clinic.js 三大子工具分工
Doctor 做全局体检,给出阻塞/泄漏概率评分和建议;Bubbleprof 专注异步调用链气泡图;Heapprofiler 生成堆采样时间序列,对比不同时间对象增长。
| 工具 | 分析维度 | 开销 | 输出格式 | 最擅长 |
|---|---|---|---|---|
| clinic doctor | CPU/内存/事件循环 | 低(<5%) | 单页HTML报告 | 首诊定位方向 |
| 0x flamegraph | CPU栈时间占比 | 低 | 交互式SVG | 找CPU热点函数 |
| clinic bubbleprof | 异步调用链延迟 | 中 | 交互式气泡图 | Promise/回调等待 |
| clinic heapprofiler | 堆对象增长曲线 | 中 | 交互式堆分析 | 内存泄漏定位 |
| --prof-process | V8底层统计 | 极低 | 文本报告 | 对比版本差异 |
最佳实践
先 doctor 扫全局再针对性深挖。压测流量必须贴近真实请求分布,否则误判。基线数据先存一份,优化后再跑对比。