node:bench 进标准库了:以后压测 Node 代码不用再装第三方跑分库,但它现在还得挂一个 flag 才敢用

Node 终于有自己的跑分工具了——node:bench 在 26.9.0 里随 node:test 一起进了标准库。不用再 npm i 一个 bench 库,用你写测试那套 bench() / suite() 就能直接跑。

但先泼盆冷水:它现在是 Stability 1.0(Early Development),而且必须带 --experimental-bench 才能用。

为什么这件事值得留意

Node 有内置测试运行器(node:test)已经很多年了,但一直没有官方 benchmark 运行器。你测性能只能靠 autocannon、benchmark.js、tinybench 这些第三方库,各自 API 不一样,跑出来的数字也没法横向对比,更别说跟 Node core 自己的 benchmark 对齐。

node:bench 的 API 是照着 node:test 设计的,学习成本几乎为零:

import { bench, suite } from 'node:bench';

suite('URL', () => {
  const input = 'https://example.com/a?b=c';
  bench('construct', { samples: 30 }, (b) => {
    b.start();
    for (let i = 0; i < 10_000; i++) new URL(input);
    b.end(10_000); // 把操作次数传进去,它才好算每 op 的耗时
  });
});

命令行跑:

node --experimental-bench --bench benchmark.mjs

三个真正实用的设计

1. 默认一个文件一个子进程

--bench-isolation=process 是默认值:每个 benchmark 文件跑在独立的子进程里,模块状态和堆内存互不污染。这点很关键——以前用第三方库,前一个用例的 JIT 预热、缓存、残留对象会悄悄影响后一个用例,你测出来的数字全是脏的。想省启动开销可以 --bench-isolation=none,但代价就是状态互相串门。

2. 结构化输出,适合接进 CI

run() 返回一个 BenchmarksStream,吐的是结构化记录,不是一段给人看的文本。你可以 .compose(spec) 打印报告,也可以接 json reporter 落到文件,再拿进流水线做趋势对比。内置的 spec reporter 里有一列 95% 置信区间(CI)。

3. 顺手补了个统计 API

配套的 perf_hooks 加了 histogram.meanCI(),用 Student’s t 分布 + 标准误算均值的双侧置信区间:

const { createHistogram } = require('node:perf_hooks');
const h = createHistogram();
for (let i = 1; i <= 100; i++) h.record(i);
const { mean, lower, upper } = h.meanCI();
// mean=50.5, 95% CI=[41.49, 59.51]

一个反常识的细节

这个模块是先以默认可用姿态发布、随后又被收回 flag 后面的。

作者 James M Snell 在评审后把它退回了实验门控,原因不是代码有问题,而是「意义判定」——in-process benchmark 太容易被做局了,自己给自己测热点路径,数字看着好看但经不起推敲。所以最终形态是:API 全都在(runFile、createRunner、bench:plan 事件、context.diagnostic),但你得显式挂 flag 才敢用。

这是好事。一个官方工具在数字可信度上保持克制,比直接给你一个漂亮的跑分然后误导优化方向要诚实得多。

你现在该做的

  1. 别急着换工具。node:bench 还是 Early Development,先保留你现有的 benchmark,另起一份 node:bench 版本并行跑,拿到跨版本基准再说。
  2. 固定条件。测出来的 duration_ns 不能当线上延迟用。固定硬件、Node flags、输入数据、warm-up 次数,否则数字没有可比性。
  3. CI 里跑趋势,不跑绝对值。接 json reporter,把结果存下来对比历史。单次运行的数字意义有限,趋势才有意义。
  4. 注意 Node 26 还是 Current。它不是 LTS(预计 2026 年 10 月才进 Active LTS),--experimental-bench 是测量工具,不是生产请求路径需要的运行时 flag。

一句话:Node 把 benchmark 这件事收进了标准库,API 照着 node:test 抄,一个 flag 就能跑,输出还是结构化的——但它挂上「实验」的牌子,恰恰是因为官方不想让你拿着一个容易做局的数字去做架构决策。

来源:

评论区

0 条评论

登录后可评论。

阿监·前端工程化 2222 阅读