使用Criterion对Rust代码进行基准测试
基准测试是用于衡量软件性能的测试,是软件测试方面的一个关键技术。Rust 在 Nightly 版本中提供了基本的基准测试(截止本文书写时间),但是并没有进入 Stable 。
简介
Criterion 是一个强大的 Rust 基准测试 Crates ,提供了对代码性能精确可靠的分析和其它各种各样的特性。从基本的基准测试,到高级的性能统计与分析,Criterion 都可以完成。
在 Rust 项目中使用 Criterion
创建项目
cargo new --lib testing
实现逻辑代码
// src/lib.rs
use std::cmp::Ordering;
pub fn binary_search(v: &[i64], target: i64, begin: usize, end: usize) -> Result<usize, &str> {
if end < begin {
return Err("NO FOUND");
}
let mid = begin + (end - begin) / 2;
match v[mid].cmp(&target) {
Ordering::Equal => Ok(mid),
Ordering::Less => return binary_search(v, target, mid + 1, end),
Ordering::Greater => return binary_search(v, target, begin, mid - 1),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_binary_search() {
let v = &[1, 2, 3, 4, 5, 6];
let success = binary_search(v, 2, 0, v.len() - 1);
assert!(success.is_ok());
assert_eq!(1, success.unwrap());
let failed = binary_search(v, 10, 0, v.len() - 1);
assert!(failed.is_err());
}
}
单元测试
cargo test
增加 criterion
cargo add --dev criterion -F html_reports
创建基准测试代码文件
mkdir -p benches
touch benches/binary_search_benchmark.rs
编写基准测试代码
// benches/binary_search_benchmark.rs
use criterion::{criterion_group, criterion_main, Criterion};
fn binary_search_benchmark(c: &mut Criterion) {
let v = &[1, 2, 3, 4, 5, 6];
let end = v.len() - 1;
c.bench_function("binary_search", |b| {
b.iter(|| testing::binary_search(v, 2, 0, end))
});
}
criterion_group!(benches, binary_search_benchmark);
criterion_main!(benches);
说明:
criterion_group!(benches, binary_search_benchmark);
:设置一个名为benches
的基准组,其中包含 binary_search_benchmark 函数
criterion_main!(benches);
: 生成一个运行基准测试的main
函数
在 Cargo.toml 中注册 benchmark 测试
[[bench]]
name = "binary_search_benchmark"
harness = false
安装GNUPlot
GNUPlot 是生成图表的工具,也可以不安装,如果没找到 GNUPlot,会使用 plotters 来生成
sudo apt install gnuplot
执行基准测试
cargo bench
此时在 target/criterion/report/index.html
就是生成的基准测试报告。
报告解读
在浏览器中打开报告,可以看到两张图。
左图显示了函数调用的时间分布和可信区间。左图下方是附加统计信息:
- Slope - 线性回归斜率的置信区间
- R^2 - 置信区间下限和上限的拟合优度值
- Mean - 平均值
- Std. Dev. - 每次迭代时间的标准偏差,如果此值偏大,说明本次基准测试存在噪声
- Median - 中位数
- MAD - 中位绝对偏差,如果此值偏大,说明本次基准测试存在噪声
右图显示了随着迭代次数增多(即代码中b的数量增大),基准测试所花费时间的变化。
基准测试的应用
当对一个函数进行优化之后,再次运行 cargo bench
, 生成的报告下方会出现 Change Since Previous Benchmark
的节,这一节表示两次基准测试的变化,图中红色部分表示上次的统计结果,蓝包部分表示最新一次的统计结果。对比两次的统计数据,即可以分析优化的影响。