Isolated benchmarks

Rust supports benchmark testing out of the box. You can use it to compare the performance of different solutions of the same problem or to get to know the time of execution of some parts of your application.

To use benchmarks, you have to add a function with the #[bench] attribute. The function expects a mutable reference to the Bencher instance. For example, let's compare cloning a String with taking a reference to it:

#![feature(test)]
extern crate test;
use test::Bencher;

#[bench]
fn bench_clone(b: &mut Bencher) {
let data = "data".to_string();
b.iter(move || {
let _data = data.clone();
});
}

#[bench]
fn bench_ref(b: &mut Bencher) {
let data = "data".to_string();
b.iter(move || {
let _data = &data;
});
}

To benchmark, you have to provide a closure with a code you want to measure to the iter method of the Bencher instance. You also need to add a test feature with #![feature(test)] to testing module and use extern crate test to import test crate to import the Bencher type from this module.

The bench_clone function has a String value and clones it on every measurement by Bencher. In bench_ref, we take a reference to a String value.

Now you can start a benchmark test with cargo:

cargo bench

It compiles the code for testing (the code items with the #[cfg(test)]  attribute will be activated) and then runs the benchmarks. For our examples, we have the following results:

running 2 tests
test bench_clone ... bench: 32 ns/iter (+/- 9)
test bench_ref ... bench: 0 ns/iter (+/- 0)

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

As we expected, taking the reference to a String takes no time, but the cloning of a String takes 32 nanoseconds per call of the clone method.

Remember, you can do good benchmark testing for CPU-bound tasks, but not I/O-bound tasks, because I/O tasks are more dependent on the quality of hardware and operating system performance.

If you want to benchmark the operation of some functions in the running application, then you have to use a profiler. Let's try to analyze some code with a profiler.