Benches

test-r provides a simple benchmark runner as well, very similar to the built-in one in unstable Rust. The main differences are that test-r allows defining async bench functions too (when the tokio feature is enabled), and that benchmark functions also support dependency injection.

Defining benchmarks

To define a benchmark, just use the #[bench] attribute instead of a #[test] attribute on a function that takes a mutable reference to a Bencher:

#![allow(unused)]
fn main() {
use test_r::{bench, Bencher};

#[bench]
fn bench1(b: &mut Bencher) {
    b.iter(|| 10 + 11);
}
}

The benchmark framework will measure the performance of the function passed to the iter method on the bencher.

If a benchmark needs shared dependencies, they can be added as additional parameters to the benchmark function. The &mut Bencher parameter must always be the first one.

#![allow(unused)]
fn main() {
use test_r::{bench, Bencher};

struct SharedDependency {
    value: i32,
}

#[bench]
fn bench2(b: &mut Bencher, shared: &SharedDependency) {
    b.iter(|| shared.value + 11);
}
}

Async benchmarks

When the tokio feature is enabled, benchmarks can be async too. Just use the #[bench] attribute on an async function that takes a mutable reference to an AsyncBencher:

#![allow(unused)]
fn main() {
use test_r::{bench, AsyncBencher};

#[bench]
async fn bench1(b: &mut AsyncBencher) {
    b.iter(|| Box::pin(async { 10 + 11 })).await;
}
}

Running benchmarks

Benchmarks are run by default as part of cargo test, but they can be also separately executed using cargo bench, or by passing the --bench flag to cargo test.