Node.js Performance Diagnostics: clinic.js & Flamegraphs
Node's async model makes debugging trickier than traditional languages. clinic.js is today's most user-friendly one-stop diagnostic suite for event-loop, promise, and memory issues.
Reading Flamegraphs: Width Equals Time
Each flamegraph box is a stack frame. Width equals CPU samples. Wide, flat top frames are hotspots. Tall upward spikes hint at deep recursion or sync IO. Seek the "flat tops" for lowest-hanging fruit.
#!/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] 部分
Three Clinic.js Sub-tools
Doctor runs a full health check with scores and fix suggestions. Bubbleprof visualizes async call chains. Heapprofiler samples heap allocation over time and compares object-type growth rates.
| Tool | Dimension | Overhead | Output | Best At |
|---|---|---|---|---|
| clinic doctor | CPU/mem/event loop | Low (<5%) | Single HTML | First-pass triage |
| 0x flamegraph | CPU stack share | Low | Interactive SVG | CPU hotspots |
| clinic bubbleprof | Async latency | Medium | Interactive bubbles | Promise waits |
| clinic heapprofiler | Heap growth timeline | Medium | Interactive heap | Memory leaks |
| --prof-process | V8 raw stats | Very Low | Text report | Version diffs |
Best Practices
Start with Doctor for a global scan then drill. Load-test traffic must reflect production distributions to avoid skewed conclusions. Capture baselines first; compare post-optimization runs.