尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
criterion.rs 的 bencher 兼容层(criterion_bencher_compat):把 bencher 基准测试平滑迁移到 Criterion.rs
开发工具性能测试【免费下载链接】criterion.rsStatistics-driven benchmarking library for Rust项目地址https://gitcode.com/gh_mirrors/cr/criterion.rs点击查看免费下载导读本文聚焦 Criterion.rs 仓库中提供的criterion_bencher_compat即bencher_compat子 crate——一个专为旧bencher基准测试打造的“兼容垫片shim”。它让你在几乎不改动基准测试代码的前提下把基于bencher的基准测试交给 Criterion.rs 驱动从而立即获得统计学显著性检验、异常值检测、回归分析、HTML 报告与图表演示等能力。读完本文你将掌握完整的迁移步骤依赖替换、导入改写、cargo bench运行与输出解读并通过源码剖析理解Bencher、benchmark_group!、benchmark_main!三个核心 API 在底层是如何桥接到 Criterion.rs 的以及它的能力边界与后续进一步迁移到原生 Criterion.rs 接口的路径。一、为什么需要一个 bencher 兼容层bencher是 Rust 生态中一个轻量级的微基准测试库许多早期项目用它编写形如fn bench_x(b: mut Bencher)的基准函数并通过benchmark_group!与benchmark_main!两个宏组织基准集合。而 Criterion.rs 是一个统计驱动的基准测试库能够执行置信区间估计、异常值检测、基线baseline比较与图形化报告功能远超bencher。但把既有bencher基准全部重写为 Criterion.rs 接口需要投入不少改造时间也让想“先试用一下 Criterion.rs”的用户望而却步。为此Criterion.rs 仓库专门维护了一个垫片 crate。正如 bencher_compat/README.md 所述This crate is a shim that can be used to easily convert mostbencherbenchmarks to Criterion.rs benchmarks.即这是一个“垫片”用于把大多数bencher基准测试轻松转换为 Criterion.rs 基准测试。它的包描述见 bencher_compat/Cargo.toml也写得很直白Drop-in replacement for commonly-used parts of Bencher——对bencher常用 API 的直接替换品。兼容层刻意只覆盖bencher最常用的 API 子集让你用最小的代码改动先跑起来如果 Criterion.rs 用起来顺手官方推荐再进一步迁移到原生接口详见后文“进一步迁移”一节。二、兼容层提供了哪些 APIcriterion_bencher_compat对外暴露的接口非常精简完整实现见 bencher_compat/src/lib.rs共四个部分API形态作用Benchera, b结构体替代bencher::Bencher作为基准回调的入参类型benchmark_group!宏替代bencher::benchmark_group!声明一组基准函数benchmark_main!宏替代bencher::benchmark_main!生成程序入口black_box/Criterion重导出pub use std::hint::black_box与pub use criterion::Criterion免去额外导入其中Bencher的声明为/// Stand-in for bencher::Bencher which uses Criterion.rs to perform the benchmark instead. pub struct Benchera, b { pub bytes: u64, pub bencher: a mut ::criterion::Bencherb, WallTime, }它内部持有一个mut criterion::Bencher默认测量类型为WallTime即墙上时钟并保留了bencher风格的bytes字段用于维持 API 兼容其核心方法iter只是把计时循环直接转发给底层 Criterion.rs 的Bencherpub fn iterT, F(mut self, inner: F) where F: FnMut() - T { self.bencher.iter(inner); }也就是说你在基准函数里写的bench.iter(|| ...)在编译期被原样委托给了 Criterion.rs 的计时引擎统计与报告全部由 Criterion.rs 完成。三、实战迁移三步把 bencher 基准换成 Criterion.rsbook/src/user_guide/bencher_compatibility.md 给出了完整的迁移示范。以下逐步复现。3.1 原始 bencher 基准假设你手头有一个典型的bencher基准文件例如来自bencher官方示例use bencher::{benchmark_group, benchmark_main, Bencher}; fn a(bench: mut Bencher) { bench.iter(|| { (0..1000).fold(0, |x, y| x y) }) } fn b(bench: mut Bencher) { const N: usize 1024; bench.iter(|| { vec![0u8; N] }); bench.bytes N as u64; } benchmark_group!(benches, a, b); benchmark_main!(benches);注意基准函数a、b都接受mut Bencher且b通过bench.bytes记录每次迭代处理的字节数用于吞吐量展示。整个迁移过程只需要改两处。3.2 第一步替换 Cargo.toml 中的依赖把[dev-dependencies] bencher 0.1改为[dev-dependencies] criterion_bencher_compat 0.4当前仓库内该 crate 的版本正是0.4.0见 bencher_compat/Cargo.toml与指南中的版本号一致。它作为dev-dependencies引入即可基准测试代码通过它间接获得 Criterion.rs 的完整能力。3.3 第二步改写基准文件的导入把文件顶部的use bencher::{benchmark_group, benchmark_main, Bencher};改为use criterion_bencher_compat as bencher; use bencher::{benchmark_group, benchmark_main, Bencher};这里有一个巧妙的细节用as bencher给兼容 crate 起别名于是基准文件里其余的代码函数签名、bench.iter、bench.bytes、两个宏的调用可以一行都不动。这正是“drop-in replacement”的体现。第三步就是把基准文件的[[bench]]段配置好harness false如果还没配置的话然后运行cargo bench3.4 第三步运行与输出解读指南给出了一个真实的运行输出示例Running target/release/deps/bencher_example-d865087781455bd5 a time: [234.58 ps 237.68 ps 241.94 ps] Found 9 outliers among 100 measurements (9.00%) 4 (4.00%) high mild 5 (5.00%) high severe b time: [23.972 ns 24.218 ns 24.474 ns] Found 4 outliers among 100 measurements (4.00%) 4 (4.00%) high mild这段输出是典型的 Criterion.rs 统计风格和bencher的简单输出有本质区别time: [下界 点估计 上界]Criterion.rs 以置信区间形式报告耗时默认为 95% 置信区间而不是单一数字Found N outliers among 100 measurements自动执行异常值检测并标注high mild高轻度与high severe高严重等级测量次数Criterion.rs 默认执行多次采样示例中为 100 次测量通过不断调整迭代次数保证统计精度。仓库中的基准示例 bencher_compat/benches/bencher_example.rs 就是按上述模式编写的harness false已在 bencher_compat/Cargo.toml 的[[bench]]段声明可以直接作为你的起点模板。四、源码级剖析两个宏如何桥接到 Criterion.rs兼容层的魔法集中在两个宏的展开逻辑里。理解它们你就理解了整个 shim 的运作机制。4.1benchmark_group!为每个函数生成一个 Criterion 基准宏定义见 bencher_compat/src/lib.rs#[macro_export] macro_rules! benchmark_group { ($group_name:ident, $($function:path),) { pub fn $group_name() { use $crate::Criterion; let mut criterion: Criterion Criterion::default().configure_from_args(); $( criterion.bench_function(stringify!($function), |b| { let mut wrapped $crate::Bencher { bytes: 0, bencher: b, }; $function(mut wrapped); }); ) } }; ($group_name:ident, $($function:path,)) { benchmark_group!($group_name, $($function),); }; }展开后它做三件事创建Criterion实例并解析命令行参数Criterion::default().configure_from_args()。configure_from_args是 Criterion.rs 的 CLI 解析入口见 src/lib.rs支持过滤器位置参数、--color、--verbose、--quiet、--noplot、--save-baseline、--baseline、--list、--format等开关为列表中的每个函数调用criterion.bench_functionbench_function见 src/lib.rs会为该函数创建独立的基准组并注册计时回调包装BencherCriterion.rs 的回调参数b: mut criterion::Bencher被包装进兼容层的Bencher { bytes: 0, bencher: b }再传给你的基准函数$function(mut wrapped)。两个模式分支带不带尾部逗号是为了兼容bencher宏对尾逗号的不同写法实质是同一个展开。4.2benchmark_main!生成统一的入口函数#[macro_export] macro_rules! benchmark_main { ($($group_name:path),) { fn main() { $( $group_name(); ) $crate::Criterion::default() .configure_from_args() .final_summary(); } }; ($($group_name:path,)) { benchmark_main!($($group_name),); }; }它生成main先依次调用每个benchmark_group!生成的pub fn $group_name()最后再构建一个Criterion实例调用final_summary()。final_summary见 src/lib.rs的作用是在整轮基准跑完后输出跨基准的总结报告如相对速度对比并且只有在当前模式为基准模式mode.is_benchmark()时才执行因此不会干扰--list、--profile-time等特殊模式。4.3 底层计时模型Bencher::iter做了什么兼容层的iter最终调用的是 Criterion.rs 的criterion::Bencher::iter见 src/bencher.rs。其时序模型在源码注释中有明确说明elapsed Instant::now iters * (routine mem::drop(O) Range::next)即iter会反复执行你的闭包iters次累计总耗时并且把闭包返回值的drop开销也计入计时。因此如果闭包返回值带有昂贵析构如大Vec计时会包含释放开销——这是刻意设计的计时模型适合返回值析构开销可忽略的场景需要精细控制计时边界时Criterion.rs 还提供了iter_custom、iter_batched、iter_batched_ref、iter_with_large_drop等更多计时循环同一文件 src/bencher.rs 的文档注释有完整说明但兼容层出于“只覆盖常用子集”的定位只转发iter。此外Criterion.rs 的iter内部对每次routine()的返回值应用了black_boxsrc/bencher.rs防止编译器把基准代码当作死代码消除这也是兼容层重导出black_box的原因。五、bytes字段与吞吐量的说明在原始bencher中bench.bytes N用于让bencher报告吞吐量bytes/s。兼容层的Bencher保留了pub bytes: u64字段以维持源码兼容——示例基准b中bench.bytes N as u64;依然能编译通过。不过需要说明在 Criterion.rs 中吞吐量并不是通过Bencher::bytes驱动而是通过BenchmarkGroup::throughput(Throughput::Bytes(...))等方式显式配置见 src/benchmark_group.rs 与 src/lib.rs 中Throughput枚举的Bytes/Elements/Bits变体。也就是说兼容层中的bytes字段只起到 API 占位的作用不会自动参与 Criterion.rs 的吞吐量统计如果你需要吞吐量报告应在迁移到原生 Criterion.rs 接口后改用throughput配置。六、特性开关real_blackboxbencher_compat/Cargo.toml 声明了一个特性[features] real_blackbox [criterion/real_blackbox] default []该特性会转发启用 Criterion.rs 的real_blackbox特性。Criterion.rs 默认尤其在非 nightly 工具链上使用较廉价的black_box近似实现启用real_blackbox后使用真实的std::hint::black_box以更强的防优化保证换取微小的调用开销。如果你对基准结果中的优化消除风险比较敏感可以在Cargo.toml中这样启用[dev-dependencies] criterion_bencher_compat { version 0.4, features [real_blackbox] }七、能力边界与后续迁移路径兼容层是有意“小而精”的。指南 book/src/user_guide/bencher_compatibility.md 明确列出了两条限制不实现bencher的完整 API只覆盖最常用的子集。如果基准用到了不支持的 API例如自定义测量、批量迭代等在试用期间可能需要临时禁用相关代码不暴露 Criterion.rs 的大多数高级特性——基线比较、参数化基准bench_with_input、BenchmarkGroup、自定义测量类型Measurementtrait、CSV 导出、HTML 报告定制等都无法通过 shim 触达。因此官方建议如果 Criterion.rs 用起来符合预期就把基准最终迁移到 Criterion.rs 原生接口。完整的迁移示范见 book/src/user_guide/migrating_from_libtest.md其要点是在Cargo.toml中声明[[bench]]段的harness false将bencher依赖替换为criterion把fn bench_x(b: mut Bencher)改写为fn bench_x(c: mut Criterion)并用c.bench_function(名字, |b| b.iter(|| ...))包裹计时闭包用criterion_group!criterion_main!生成入口。完成这一步后你就能全面使用 Criterion.rs 的基准组、输入参数化、吞吐量统计、自定义测量与 HTML 报告等能力。八、参考文件索引想深入钻研的读者可以继续阅读仓库中的以下文件bencher_compat/README.md兼容层的 crate 级说明本文主体文档bencher_compat/src/lib.rsBencher、benchmark_group!、benchmark_main!的完整实现bencher_compat/Cargo.toml依赖声明与real_blackbox特性bencher_compat/benches/bencher_example.rs可直接运行的工作示例book/src/user_guide/bencher_compatibility.md官方用户指南中的兼容层章节book/src/user_guide/migrating_from_libtest.md从 libtest/bencher 迁移到原生 Criterion.rs 的完整示范src/bencher.rsCriterion.rs 底层Bencher与各计时循环的时序模型src/lib.rsconfigure_from_args、final_summary、bench_function的实现src/benchmark_group.rsthroughput等高级配置的入口总结criterion_bencher_compat是 Criterion.rs 为bencher用户准备的“零摩擦入场券”——改两行配置、加一行as bencher别名即可用上统计驱动的基准测试基础设施而其精简的 API 表面也暗示了它的定位是过渡工具真正发挥 Criterion.rs 全部实力仍建议最终迁移到原生接口。赞分享开发工具性能测试【免费下载链接】criterion.rsStatistics-driven benchmarking library for Rust项目地址https://gitcode.com/gh_mirrors/cr/criterion.rs点击查看免费下载相关推荐Criterion.rs与Bencher兼容从传统基准测试平滑迁移的终极指南Criterion.rs与Bencher兼容从传统基准测试平滑迁移的终极指南 Criterion.rs作为Rust生态中统计驱动的基准测试库提供了与Benc开发工具性能测试3步打造你的AI梦想伙伴让虚拟角色走进现实生活3步打造你的AI梦想伙伴让虚拟角色走进现实生活 你是否曾幻想过与心爱的动漫角色对话是否希望有一个懂你、陪伴你的AI伙伴My Dream Moments正是人工智能大模型AI 应用交互助手RepoDB枚举处理详解数据库枚举字段的最佳实践指南RepoDB枚举处理详解数据库枚举字段的最佳实践指南 RepoDB作为一款高效的.NET混合ORM库为开发者提供了强大的枚举字段处理能力。在前100个字内后端上一篇终极指南在Mac上免费实现NTFS硬盘读写完整解决方案下一篇SciPy 的 cython_lapack在 Cython 中直接调用 LAPACK 的官方 Cython 级封装指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

高频变压器设计:难点不在算,而在权衡

高频变压器设计:难点不在算,而在权衡

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/12 4:17:37
自动化老工程师90条实战经验:从入行到现场高手的完整指南

自动化老工程师90条实战经验:从入行到现场高手的完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/12 4:17:37
Docker 下搭建 Redis 集群:三主三从、故障转移与扩容实战

Docker 下搭建 Redis 集群:三主三从、故障转移与扩容实战

Docker 下搭建 Redis 集群,听起来就是拉镜像、起容器、敲一条 create 命令的事,但真正把三主三从跑起来,再经历过一次故障切换和扩容,才知道里面有不少细节是官方文档不会明确告诉你的。我会把一条完整的实操链路走完:…

📅 2026/10/12 4:12:37
MORE NEWS

更多资讯

📰

【港口与特殊场景电缆防盗篇-多场景适配的安防方案】

港口作为重要基础设施,其电缆系统面临着独特的安全挑战。港口区域通常面积广大、设备分布分散、人员流动性强,电缆设施容易成为盗窃目标。港口电缆防盗报警监控系统是一种专门为保障港口电缆设施安全而设计的综合安防系统。 沃思智能电缆防盗装置具备报警…

📰

YOLO盲道及障碍物检测数据集 深度学习框架目标检测算法训练盲道及障碍物检测数据集

使用深度学习框架目标检测算法训练盲道及障碍物检测数据集,并通过建立gui界面检测道路中的盲道及障碍物识别。 文章目录使用深度学习框架目标检测算法训练盲道及障碍物检测数据集,并通过建立gui界面检测道路中的盲道及障碍物识别。安装依赖数据集准备配置…

📰

小白程序员必看:轻松入门医疗大模型,开启智能医疗新机遇!

医疗大模型作为通用AI与医疗场景的深度融合产物,已具备辅助诊疗、药物研发等全链条赋能能力。中国医疗大模型产业政策完善、规模快速扩容、技术实力跃升,市场渗透率持续攀升。尽管面临合规、数据治理等挑战,但其在全球评测、场景落地中形成优…

📰

YOLO26 单卡 RTX 4090 24GB 训练教程:自定义数据集、显存优化与云 GPU 部署

摘要: YOLO26 如何使用自己的数据集训练?单张 RTX 4090 24GB 显存够不够?本文基于 Ultralytics YOLO26,介绍从 CUDA/PyTorch 环境配置、数据集标注、data.yaml 编写,到模型训练、mAP 验证、CUDA OOM 优化及断点续训的完…

📰

FDE(前沿部署工程师)年入百万?收藏!深度解析这个岗位为何最长火不过五年及应对策略

本文分析了FDE岗位的五个结构性死穴,指出其设计问题而非技术问题,导致效率低下和混乱。文章还揭示了行业对FDE岗位的认知盲区,包括可用性启发式、近因偏差、锚定效应、基率忽视、自动化偏见和功能固着。对于尚未设立FDE岗位的企业&#xff0c…

📰

SpringBoot+Vue+MySQL美食网站毕设实战:从架构设计到部署上线全解析

每年到毕业季,总有人被选题折磨得睡不着觉。如果你正打算做一套“SpringBootVueMySQL 的BS架构美食网站平台”作为毕业设计,或者已经选了类似的题目但脑子里还是一团乱麻,那么这篇内容就是为你准备的。我把自己从选题、拆需求、搭数据库、写后…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬