Struct criterion::Bencher

source ·
pub struct Bencher { /* private fields */ }
Expand description

Helper struct to time routines

This struct provides different timing loops as methods. Each timing loop provides a different way to time a routine and each has advantages and disadvantages.

  • If your routine returns a value with an expensive drop method, use iter_with_large_drop.
  • If your routine requires some per-iteration setup that shouldn’t be timed, use iter_with_setup or (if the setup is expensive) use iter_with_large_setup to construct a pool of input data ahead of time
  • Otherwise, use iter.

Implementations

Times a routine by executing it many times and timing the total elapsed time.

Prefer this timing loop when routine returns a value that doesn’t have a destructor.

Timing loop
let start = Instant::now();
for _ in 0..iters {
    routine();
}
let elapsed = start.elapsed();
Timing model

Note that the Bencher also times the time required to destroy the output of routine(). Therefore prefer this timing loop when the runtime of mem::drop(O) is negligible compared to the runtime of the routine.

elapsed = Instant::now + iters * (routine + mem::drop(O) + Range::next)
Example
#[macro_use] extern crate criterion;

use criterion::*;

// The function to benchmark
fn foo() {
    // ...
}

fn bench(c: &mut Criterion) {
    c.bench_function("iter", move |b| {
        b.iter(|| foo())
    });
}

criterion_group!(benches, bench);
criterion_main!(benches);

Times a routine that requires some setup on each iteration.

For example, use this loop to benchmark sorting algorithms because they require unsorted data on each iteration.

Example
#[macro_use] extern crate criterion;

use criterion::*;

fn create_scrambled_data() -> Vec<u64> {
    // ...
}

// The sorting algorithm to test
fn sort(data: &mut [u64]) {
    // ...
}

fn bench(c: &mut Criterion) {
    let data = create_scrambled_data();

    c.bench_function("with_setup", move |b| {
        // This will avoid timing the to_vec call.
        b.iter_with_setup(|| data.to_vec(), |mut data| sort(&mut data))
    });
}

criterion_group!(benches, bench);
criterion_main!(benches);
Timing loop
let mut elapsed = Duration::new(0, 0);
for _ in 0..iters {
    let input = setup();

    let start = Instant::now();
    let output = routine(input);
    let elapsed_in_iter = start.elapsed();

    mem::drop(output);

    elapsed = elapsed + elapsed_in_iter;
}
Timing model
elapsed = iters * (Instant::now + routine)

Times a routine by collecting its output on each iteration. This avoids timing the destructor of the value returned by routine.

WARNING: This requires iters * mem::size_of::<O>() of memory, and iters is not under the control of the caller.

Timing loop
let mut outputs = Vec::with_capacity(iters);

let start = Instant::now();
for _ in 0..iters {
    outputs.push(routine());
}
let elapsed = start.elapsed();

mem::drop(outputs);
Timing model
elapsed = Instant::now + iters * (routine) + Iterator::collect::<Vec<_>>
Example
#[macro_use] extern crate criterion;

use criterion::*;

fn create_vector() -> Vec<u64> {
    // ...
}

fn bench(c: &mut Criterion) {
    c.bench_function("with_drop", move |b| {
        // This will avoid timing the Vec::drop.
        b.iter_with_large_drop(|| create_vector())
    });
}

criterion_group!(benches, bench);
criterion_main!(benches);

Times a routine that needs to consume its input by first creating a pool of inputs.

This function is handy for benchmarking destructors.

WARNING This requires iters * mem::size_of::<I>() of memory, and iters is not under the control of the caller.

Timing loop
let inputs: Vec<()> = (0..iters).map(|_| setup()).collect();
let start = Instant::now();

for input in inputs {
    routine(input);
}

let elapsed = start.elapsed();
Timing model
elapsed = iters * (Instant::now + routine)
Example
#[macro_use] extern crate criterion;

use criterion::*;

fn create_data() -> Vec<u64> {
    // ...
}

fn use_data(data: &mut [u64]) {
    // ...
}

fn bench(c: &mut Criterion) {
    c.bench_function("with_setup", move |b| {
        // This will avoid timing the create_data call.
        b.iter_with_large_setup(|| create_data(), |mut data| use_data(&mut data))
    });
}

criterion_group!(benches, bench);
criterion_main!(benches);

Trait Implementations

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.