概要
Rustには公式ベンチマークツールがあるが現状unstableなのでnightlyでしかコンパイルできない。 だからプロジェクトがstableだと使えないんかなー、と思って調べてみたらやり方があったのでメモしておく。
試してみる
プロジェクトを用意
$ cargo new --lib hello_bench $ cd hello_bench
新規プロジェクトを作ったあとはベンチマーク対象のコードと、一応テストコードでも書いておく。
src/lib.rsを下記のように変更。
pub fn sum(x: u8, y: u8) -> u8 { x + y } #[cfg(test)] mod tests { use super::*; #[test] fn sum_test() { assert_eq!(sum(2, 3), 5); } }
特にunstableな機能を使っていないので、stableでテストが通る。
$ cargo test
Compiling hello_bench v0.1.0 (/Users/yamash723/Workspace/labo/rust/hello_bench)
Finished dev [unoptimized + debuginfo] target(s) in 0.38s
Running target/debug/deps/hello_bench-a775e998ab4d2775
running 1 test
test tests::sum_test ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Doc-tests hello_bench
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
ベンチマークコードをプロジェクトに追加
もしもnightlyなプロジェクトであればsrc/lib.rsに追加すれば動くといえば動くんだけども、
#[bench]属性の関数であっても#[cfg(test)]配下であればcargo test時に実行されてしまうのでおすすめできない。
そこで、benchesというベンチマークコードを配置するためのオプショナルディレクトリがRustには用意されているので、そこにコードを配置する。
$ mkdir benches $ touch benches/bench.rs
benchesはcargo bench実行時にのみビルドされるので、プロジェクトのメインコードと切り分けることができる。
とりあえず先程作成した関数をベンチマークするコードをbenches/bench.rsに追加する。
#![feature(test)] extern crate test; #[bench] fn sum_bench(b: &mut test::Bencher) { b.iter(|| hello_bench::sum(2, 3)) }
評価対象の関数の呼び出しはhello_bench::sum(2, 3)のようにパッケージ名経由で行えばよい。
なおベンチマーク実行時、benches直下のファイルはすべてビルド対象になるのでファイル名に特に決まりはない。
コード量が多くなってきたら各ベンチマークコードをサブモジュール化してbench.rsで参照するような形にするとスッキリすると思う。
そしてベンチマークを実行する際、下記のようにnightly指定でcargoを実行すればベンチマークを実行することができる。
$ cargo +nightly bench]
Compiling hello_bench v0.1.0 (/Users/yamash723/Workspace/labo/rust/hello_bench)
Finished release [optimized] target(s) in 0.45s
Running target/release/deps/hello_bench-c6eaba87c0013faa
running 1 test
test tests::sum_test ... ignored
test result: ok. 0 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out
Running target/release/deps/bench-e4ecc1d2436f81bb
running 1 test
test sum_bench ... bench: 1 ns/iter (+/- 0)
test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out**
これでプロジェクトのメインコードはstableのままベンチマークを実行することができるようになった。