寻求进行精确微基准测试的 Rust 开发者经常发现,像 Criterion 这样的标准工具缺乏 Go 生态系统中常见的特定功能。具体而言,Criterion 不原生支持跟踪堆内存分配(B/op),缺乏标准的 pprof 分析集成,并且使用线性渐变采样模型,这可能会在微秒级的循环中引入方差和开销。这些限制使得在 Rust 和 Go 实现之间进行直接的 A/B 对比,或者在不同提交之间跟踪内存抖动回归变得困难。

为了填补这一空白,Bartek Płotka 开发了 benchfmt.rs,这是一个零依赖的 Rust 基准测试运行器和 Criterion 转换器。该工具通过提供线程本地堆分配计数器(CountingAlloc)和 pprof 分析器集成,模仿了 Go 的 `testing.B` 框架。它支持 `/key=value` 子基准测试命名,这允许基于 Go 的 `benchstat` 工具跨不同维度(如语言或样本大小)进行透视。对于现有项目,转换器可以接收 Criterion 输出并生成与 Go 兼容的 `benchfmt` 格式,从而能够使用 `benchstat` 进行抗离群值的中位数计算和 Mann-Whitney U 检验。

benchfmt.rs 项目的宣传图,展示其与 Go 基准测试工作流的集成。
benchfmt.rs 项目旨在将 Go 风格的基准测试遥测数据引入 Rust 生态系统。www.bwplotka.dev

这张图片是 benchfmt.rs 工具的主要视觉展示,该工具为 Rust 开发者复制了 Go 的基准测试生态系统。

该工具根据用户的需求提供不同的路径。`benchfmt::Suite` 运行器适用于需要精确堆内存和分析数据的全新微基准测试,因为它会捕获作用域内的 `-cpuprofile` 和 `-memprofile` 文件。相反,`benchfmt` CLI 转换器最适合那些已经使用 Criterion 且只需生成 `benchstat` 表格而无需修改底层基准测试代码的仓库。虽然 Criterion 仍然是生成内置 HTML 和 SVG 图表的标准,但 benchfmt.rs 提供了高保真性能工程所需的特定遥测数据——例如每操作的堆字节和分配计数。

一个技术区别在于采样模型。Criterion 默认使用 100 个线性渐变样本,这可能会放大方差并增加计时开销。相比之下,benchfmt.rs 模仿 Go 的稳态周期(steady-state epochs),其中固定的迭代次数针对特定的时间窗口(例如 2 秒)进行校准,并在独立的运行中重复。这为那些计时器开销干扰可能会扭曲结果的极快操作提供了更可靠的结果。然而,由于转换器通过对 Criterion 的样本数组进行分桶来近似这些周期,因此结果是稳态模型的近似,而非对 Go 内部运行时行为的完美复制。