Quickstart
Suppose the crate's binary is called my-foo
and this binary takes a file path
as positional argument. This first example shows the basic usage of the
high-level api with the #[binary_benchmark]
attribute:
extern crate iai_callgrind; macro_rules! env { ($m:tt) => {{ "/some/path" }} } use iai_callgrind::{binary_benchmark, binary_benchmark_group, main}; #[binary_benchmark] #[bench::some_id("foo.txt")] fn bench_binary(path: &str) -> iai_callgrind::Command { iai_callgrind::Command::new(env!("CARGO_BIN_EXE_my-foo")) .arg(path) .build() } binary_benchmark_group!( name = my_group; benchmarks = bench_binary ); fn main() { main!(binary_benchmark_groups = my_group); }
If you want to try out this example with your crate's binary, put the above code
into a file in $WORKSPACE_ROOT/benches/binary_benchmark.rs
. Next, replace
my-foo
in env!("CARGO_BIN_EXE_my-foo")
with the name of a binary of your
crate.
Note the env!
macro is a rust
builtin macro and CARGO_BIN_EXE_<name>
is documented
here.
You should always use env!("CARGO_BIN_EXE_<name>")
to determine the path to
the binary of your crate. Do not use relative paths like target/release/my-foo
since this might break your benchmarks in many ways. The environment variable
does exactly the right thing and the usage is short and simple.
Lastly, adjust the argument of the Command
and add the following to your
Cargo.toml
:
[[bench]]
name = "binary_benchmark"
harness = false
Running
cargo bench
presents you with something like the following:
binary_benchmark::my_group::bench_binary some_id:("foo.txt") -> target/release/my-foo foo.txt
Instructions: 342129|N/A (*********)
L1 Hits: 457370|N/A (*********)
L2 Hits: 734|N/A (*********)
RAM Hits: 4096|N/A (*********)
Total read+write: 462200|N/A (*********)
Estimated Cycles: 604400|N/A (*********)
As opposed to library benchmarks, binary benchmarks have access to a low-level api. Here, pretty much the same as the above high-level usage but written in the low-level api:
extern crate iai_callgrind; macro_rules! env { ($m:tt) => {{ "/some/path" }} } use iai_callgrind::{BinaryBenchmark, Bench, binary_benchmark_group, main}; binary_benchmark_group!( name = my_group; benchmarks = |group: &mut BinaryBenchmarkGroup| { group.binary_benchmark(BinaryBenchmark::new("bench_binary") .bench(Bench::new("some_id") .command(iai_callgrind::Command::new(env!("CARGO_BIN_EXE_my-foo")) .arg("foo.txt") .build() ) ) ) } ); fn main() { main!(binary_benchmark_groups = my_group); }
If in doubt, use the high-level api. You can still migrate to the low-level api very easily if you really need to. The other way around is more involved.