如何使用 criterion 检测回归?
解读
在国内 Rust 岗位面试中,性能回归检测是高频考点。面试官不仅想知道“会不会用”,更关注“如何落地到 CI”“如何设定阈值”“如何与 baseline 比对”。回答时要体现工程闭环:基准代码 → 持续采集 → 自动告警 → 根因定位,避免只讲 API 调用。
知识点
- criterion 设计哲学:采样统计(bootstrap 置信区间)、历史持久化(target/criterion 目录)、自动回归判定(±临界值)。
- 回归判定规则:默认 99.9% 置信区间重叠即“无回归”;若新区间整体偏移超过 ±3% 即判回归(可自定义
change阈值)。 - baseline 管理:
cargo bench --save-baseline master把主分支结果存为“真值”;PR 阶段cargo bench --baseline master自动比较。 - CI 集成要点:
- 自托管 runner 保证硬件一致;
- 关闭 CPU 变频与超线程,绑定核隔离干扰;
- 缓存
target/criterion与 baseline,避免冷编译噪声。
- 统计显著性:criterion 输出
p-value与effect size,若p < 0.05且effect size > 0.02即高置信回归,需人工复核。 - 常见误用:
- 只跑单次测量,忽略采样误差;
- 把
black_box放错位置,导致编译器优化掉核心路径; - 在虚拟机或容器里跑,未锁定
cpu-manager-policy=static,结果漂移。
答案
- 在
benches/下编写基准:
use criterion::{criterion_group, criterion_main, Criterion, black_box};
fn fib(n: u64) -> u64 { if n < 2 { 1 } else { fib(n - 1) + fib(n - 2) } }
fn bench_fib(c: &mut Criterion) {
c.bench_function("fib 20", |b| b.iter(|| fib(black_box(20))));
}
criterion_group!(benches, bench_fib);
criterion_main!(benches);
- 保存主分支 baseline:
cargo bench --bench fib --save-baseline master
结果持久化到 target/criterion/master。
- 在功能分支检测回归:
cargo bench --bench fib --baseline master
若控制台出现 Performance has regressed. 且 HTML 报告 change 列红色箭头,即判定回归。
- 自定义阈值(例如 ±1%):
let mut c = Criterion::default()
.measurement_time(Duration::from_secs(10))
.confidence_level(0.99)
.noise_threshold(0.01);
- CI 集成脚本(GitHub Actions 示例):
- name: Restore baseline
uses: actions/cache@v3
with:
path: target/criterion
key: criterion-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}
- name: Run benchmark
run: |
sudo cpupower frequency-set -g performance
cargo bench --bench fib --baseline master --output-format bencher | tee result.txt
if grep -q "Performance has regressed" result.txt; then
echo "::error::检测到性能回归,请查看报告"
exit 1
fi
- 根因定位:
- 打开
target/criterion/report/index.html,查看Change与Distribution图; - 若新增分支引入额外
clone,火焰图会显示热点; - 使用
perf dso对比汇编,确认是否生成多余内存屏障。
- 打开
拓展思考
- 微基准 vs 端到端:criterion 适合微基准,对 IO 密集场景需配合
hyperfine或locust。 - 跨平台一致性:ARM 与 x86 指令集差异大,建议分架构保存 baseline,避免误判。
- 二进制大小回归:结合
cargo-bloat与cargo-audit,在 CI 中并行检查“性能+体积+安全”三维回归。 - 生产流量回放:把真实请求录制为
*.proto,用criterion的throughput模式重放,实现“真数据”防回归。 - Rust 1.83 起
cargo bench原生支持#[bench],但 criterion 仍是事实标准,因其统计模型更严谨;面试时可主动对比两者差异,体现社区演进敏感度。