🔥 面向真实 async / await 场景的 Node.js / CLI 性能分析工具
wukong-profiler 是一个轻量、准确、可用于 CI 的 wall-time profiler,专注解决一个核心问题:
在真实的异步 Node.js 程序中,时间到底花在哪里?
✅ 原生支持 async / await(真实 wall-time)
✅ 层级嵌套步骤(Flame Tree 结构,而非平铺日志)
✅ HOT / SLOW 自动标记
✅ CPU / I/O 自动分类(heuristic)
✅ 自动给出性能解释建议
✅ Chrome Trace 导出(Chrome / Perfetto)
✅ 性能回归 diff(CI 友好)
✅ **零侵入、零魔法、可预测
npm install wukong-profiler
yarn add wukong-profiler
或直接使用 npx:
npx wukong-profiler [options]
npx wukong-profiler report ./profile.json
# 从 profile.json 生成 HTML 报告
npx wukong-profiler report ./profile.json
要进行 profile,请使用编程 API(createProfiler)或查看 examples/ 目录中的示例。
⏱ Total 28.52 s
├─ getGitLogsFast 957.78 ms ⚠ SLOW [IO]
│ ↳ Likely I/O-bound (serial await or blocking I/O)
├─ getOvertimeStats 26.39 s 🔥 HOT [CPU]
│ ↳ Likely CPU-bound (loops or heavy computation)
│ ↳ Deep call stack — consider flattening logic
谁是 HOT 路径
是 CPU 还是 I/O 问题
是不是 await 串行
是不是调用层级过深
# 从 profile.json 生成 HTML 报告
npx wukong-profiler report ./profile.json
# 生成并自动在浏览器打开
npx wukong-profiler report ./profile.json --open
# 指定输出 HTML 文件
npx wukong-profiler report ./profile.json -o my-report.html
用法:npx wukong-profiler report <profile>
<profile> 是要生成报告的 profile.json 文件路径(必填)。
| 参数 | 说明 |
|---|---|
-o, --output <file> |
输出 HTML 文件(默认:”wukong-report.html”) |
--profile |
保存的 profile JSON 文件,用于分析 |
--open |
生成后在默认浏览器中打开报告 |
注意:CLI 目前仅暴露
report子命令。要运行 profiling,请使用编程 API(createProfiler)或查看examples/目录。查看report子命令帮助:npx wukong-profiler report -h。
import { createProfiler } from 'wukong-profiler'
const profiler = createProfiler({
enabled: true,
flame: true,
profileFile: 'artifacts/profile.json', // 将 profile 输出到指定目录
traceFile: 'artifacts/trace.json',
hotThreshold: 0.8
})
// 示例:在 CI 中将输出写入 artifacts/ 目录
// const profiler = createProfiler({ enabled: true, profileFile: 'artifacts/profile.json', traceFile: 'artifacts/trace.json' })
profiler.step('load config', () => {
loadConfig()
})
await profiler.stepAsync('fetch data', async () => {
await fetchRemoteData()
})
profiler.end('Total')
stepAsync?在 Node.js 中:
await 会释放事件循环
同步 profiler 无法正确统计 wall-time
wukong-profiler 明确区分 sync / async
await profiler.stepAsync('getGitLogsFast', async () => {
await readGitLogs()
})
await profiler.stepAsync('getOvertimeStats', async () => {
await calculateStats()
})
✔ 完整 async wall-time
✔ 正确的嵌套结构
✔ I/O vs CPU 自动分类
✔ 可用于 CI / diff
createProfiler(options)创建并返回一个 profiler 实例。
| 参数名 | 默认值 | 说明 |
|---|---|---|
enabled |
false |
是否启用 profiler(输出 & JSON) |
verbose |
false |
输出更详细的日志 |
flame |
false |
输出 Flame 风格的树结构 |
slowThreshold |
500 |
慢步骤阈值(毫秒) |
hotThreshold |
0.8 |
HOT 步骤占比阈值 |
traceFile |
undefined |
Chrome Trace 输出文件 |
profileFile |
profile.json |
profile JSON 文件 存储路径 |
failOnHot |
false |
检测到 HOT 步骤时 CI 失败 |
diffBaseFile |
undefined |
用于 diff 的基准 profile |
diffThreshold |
0.2 |
性能回退阈值 |
profiler.step(name, fn)测量一个 同步步骤。
profiler.step('parse config', () => {
parseConfig()
})
profiler.stepAsync(name, asyncFn)测量异步步骤(推荐),完整 wall-time。
await profiler.stepAsync('fetch users', async () => {
await fetchUsers()
})
profiler.measure(name, fn)step 的别名(仅同步)。
⚠️ 对 async 场景,推荐使用
stepAsync,语义更清晰。
profiler.end(label?)结束 profiling 并输出结果。
profiler.end('Total')
profiler.summary(options?)获取结构化数据(适合 CI / 上报)。
const summary = profiler.summary({ top: 3 })
summary.top.forEach((step) => {
console.log(step.name, step.ratio)
})
const summary = profiler.summary({ top: 3 })
node examples/basic.mjs
node examples/flame.mjs
node examples/async.mjs
node examples/basic.mjs
然后在浏览器中打开:
chrome://tracing
加载生成的 trace 文件。
或使用 Perfetto(推荐):
https://ui.perfetto.dev
将生成的 trace 文件拖入即可查看。