Nightly Rustで有効化されるtest crateにはベンチマークを取る機能があります。
#![feature(test)]
extern crate test;
pub fn add_two(a: i32) -> i32 {
a + 2
}
#[cfg(test)]
mod tests {
use super::*;
use test::Bencher;
#[bench]
fn bench_add_two(b: &mut Bencher) {
b.iter(|| add_two(2));
}
}
(ベンチマークテストより抜粋)
$ cargo bench
Compiling adder v0.0.1 (file:///home/steve/tmp/adder)
Running target/release/adder-91b3e234d4ed382a
running 2 tests
test tests::it_works ... ignored
test tests::bench_add_two ... bench: 1 ns/iter (+/- 0)
test result: ok. 0 passed; 0 failed; 1 ignored; 1 measured
このように、cargo bench
を実行するとベンチマークテストを実行してくれます。早すぎてベンチマークが上手くとれない場合は自動的に何回か実行して平均値を出してくれます。
しかしプログラムの実行では様々な要因で速度が変化するため、例えばmaster
ブランチから何か高速化を行ったブランチfeature/faster
でのベンチマーク結果が偶然早かっただけなのか、有意に性能向上が行われたのかを評価する必要があります
criterion.rs
それを自動的に行ってくれるのがbheisler/criterion.rsです。これはtest crateと違ってStable Rustで動作します。
[dev-dependencies]
criterion = "0.3"
[[bench]]
name = "my_benchmark"
harness = false
cargo bench
コマンドにはCargo.toml
にある[[bench]]
の設定を見てベンチマークを実行する機能があります。
Setting the keys autobins, autoexamples, autotests, or autobenches to false in the [package] section will disable auto-discovery of the corresponding target type.
https://doc.rust-lang.org/cargo/reference/manifest.html#target-auto-discovery
ちなみに自動検出機能は無効化する事も出来ます。harness = false
はテスト用のランタイムを使わない設定で、criterion
が代わりに実行機能を提供してくれます。[[bench]]
のように2重括弧になってるのはTOMLのテーブル記法で、JSONで言うと
{
"bench": [
{ "name": "my_benchmark", "harness": false }
]
}
のような意味になります。これでbenches/my_benchmark.rs
を実行してくれます。
#[macro_use]
extern crate criterion;
use criterion::Criterion;
use criterion::black_box;
fn fibonacci(n: u64) -> u64 {
match n {
0 => 1,
1 => 1,
n => fibonacci(n-1) + fibonacci(n-2),
}
}
fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("fib 20", |b| b.iter(|| fibonacci(black_box(20))));
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
test crateを意識して作ってるので使い方は概ね分かると思います。詳しくはドキュメントを見てください。
$ cargo bench
Finished release [optimized] target(s) in 0.02s
Running target/release/deps/bench_cri-5f525a32c3c684a8
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Running target/release/deps/my_benchmark-37b634fc2faf7ab4
fib 20 time: [19.834 us 19.894 us 19.951 us]
change: [+0.7446% +1.9224% +3.1291%] (p = 0.00 < 0.05)
Change within noise threshold.
Found 5 outliers among 100 measurements (5.00%)
1 (1.00%) low mild
3 (3.00%) high mild
1 (1.00%) high severe
また同時に target/criterion
以下にHTMLのレポートが生成されています。