概要
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のままベンチマークを実行することができるようになった。