Rust by Example

45 Benchmarking

Rust provides infrastructure for benchmarking via the Bencher struct and the #[bench] attribute. Details in the source code below.

// bench.rs
#![feature(test)]

extern crate test;

use std::mem::replace;
use test::Bencher;

// bench: find the `BENCH_SIZE` first terms of the fibonacci sequence
static BENCH_SIZE: usize = 20;

// recursive fibonacci
fn fibonacci(n: usize) -> u32 {
    if n < 2 {
        1
    } else {
        fibonacci(n - 1) + fibonacci(n - 2)
    }
}

// iterative fibonacci
struct Fibonacci {
    curr: u32,
    next: u32,
}

impl Iterator for Fibonacci {
    type Item = u32;
    fn next(&mut self) -> Option<u32> {
        let new_next = self.curr + self.next;
        let new_curr = replace(&mut self.next, new_next);

        Some(replace(&mut self.curr, new_curr))
    }
}

fn fibonacci_sequence() -> Fibonacci {
    Fibonacci { curr: 1, next: 1 }
}

// function to benchmark must be annotated with `#[bench]`
#[bench]
fn recursive_fibonacci(b: &mut Bencher) {
    // exact code to benchmark must be passed as a closure to the iter
    // method of Bencher
    b.iter(|| {
        (0..BENCH_SIZE).map(fibonacci).collect::<Vec<u32>>()
    })
}

#[bench]
fn iterative_fibonacci(b: &mut Bencher) {
    b.iter(|| {
        fibonacci_sequence().take(BENCH_SIZE).collect::<Vec<u32>>()
    })
}

The source needs to be compiled using the --test flag, and the --bench flag must be passed to the resulting binary.

$ rustc --test -O bench.rs
$ ./bench --bench
running 2 tests
test iterative_fibonacci ... bench:       191 ns/iter (+/- 16)
test recursive_fibonacci ... bench:     49670 ns/iter (+/- 522)

test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured