Custom Test Framework
Nightly versions of the rust compiler support custom test frameworks. Criterion.rs provides an
experimental implementation of a custom test framework, meaning that you can use #[criterion]
attributes to mark your benchmarks instead of the normal criterion_group!/criterion_main!
macros.
Right now this requires some unstable features, but at some point in the future
criterion_group!/criterion_main!
will be deprecated and #[criterion]
will become the standard
way to define a Criterion.rs benchmark. If you'd like to try this feature out early, see the
documentation below.
Using #[criterion]
Since custom test frameworks are still unstable, you will need to be using a recent nightly compiler. Once that's installed, add the dependencies to your Cargo.toml:
[dev-dependencies]
criterion = "0.3"
criterion-macro = "0.3"
Note that for #[criterion]
benchmarks, we don't need to disable the normal testing harness
as we do with regular Criterion.rs benchmarks.
Let's take a look at an example benchmark (note that this example assumes you're using Rust 2018):
#![allow(unused)] #![feature(custom_test_frameworks)] #![test_runner(criterion::runner)] fn main() { use criterion::{Criterion, black_box}; use criterion_macro::criterion; fn fibonacci(n: u64) -> u64 { match n { 0 | 1 => 1, n => fibonacci(n - 1) + fibonacci(n - 2), } } fn custom_criterion() -> Criterion { Criterion::default() .sample_size(50) } #[criterion] fn bench_simple(c: &mut Criterion) { c.bench_function("Fibonacci-Simple", |b| b.iter(|| fibonacci(black_box(10)))); } #[criterion(custom_criterion())] fn bench_custom(c: &mut Criterion) { c.bench_function("Fibonacci-Custom", |b| b.iter(|| fibonacci(black_box(20)))); } }
The first thing to note is that we enable the custom_test_framework
feature and declare that we
want to use criterion::runner
as the test runner. We also import criterion_macro::criterion
,
which is the #[criterion]
macro itself. In future versions this will likely be re-exported from
the criterion
crate so that it can be imported from there, but for now we have to import it from
criterion_macro
.
After that we define our old friend the Fibonacci function and the benchmarks. To create a
benchmark with #[criterion]
you simply attach the attribute to a function that accepts an &mut Criterion
. To provide a custom Criterion object (to override default settings or similar) you can
instead use #[criterion(<some_expression_that_returns_a_criterion_object>)]
- here we're calling
the custom_criterion
function. And that's all there is to it!
Keep in mind that in addition to being built on unstable compiler features, the API design for Criterion.rs and its test framework is still experimental. The macro subcrate will respect SemVer, but future breaking changes are quite likely.