Generic benchmark functions

Benchmark functions can be generic. And setup and teardown functions, too. There's actually not much more to say about it since generic benchmark (setup and teardown) functions behave exactly the same way as you would expect it from any other generic function.

However, there is a common pitfall. If you have a function count_lines_in_file_fast which expects as parameter a PathBuf and although it is convenient especially when you have to specify many paths, don't do this:

extern crate iai_callgrind;
mod my_lib { pub fn count_lines_in_file_fast(_path: std::path::PathBuf) -> u64 { 1 } }
use iai_callgrind::{library_benchmark, library_benchmark_group, main};

use std::hint::black_box;
use std::path::PathBuf;

#[library_benchmark]
#[bench::first("path/to/file")]
fn generic_bench<T>(path: T) -> u64 where T: Into<PathBuf> {
    black_box(my_lib::count_lines_in_file_fast(black_box(path.into())))
}

library_benchmark_group!(name = my_group; benchmarks = generic_bench);
fn main() {
main!(library_benchmark_groups = my_group);
}

Since path.into() is called in the benchmark function itself, the conversion from a &str to a PathBuf is attributed to the benchmark metrics. This is almost never what you intended. You should instead convert the argument to a PathBuf in a generic setup function like that:

extern crate iai_callgrind;
mod my_lib { pub fn count_lines_in_file_fast(_path: std::path::PathBuf) -> u64 { 1 } }
use iai_callgrind::{library_benchmark, library_benchmark_group, main};

use std::hint::black_box;
use std::path::PathBuf;

fn convert_to_pathbuf<T>(path: T) -> PathBuf where T: Into<PathBuf> {
    path.into()
}

#[library_benchmark]
#[bench::first(args = ("path/to/file"), setup = convert_to_pathbuf)]
fn not_generic_anymore(path: PathBuf) -> u64 {
    black_box(my_lib::count_lines_in_file_fast(path))
}

library_benchmark_group!(name = my_group; benchmarks = not_generic_anymore);
fn main() {
main!(library_benchmark_groups = my_group);
}

That way you can still enjoy the convenience to use string literals instead of PathBuf in your #[bench] (or #[benches]) arguments and have clean benchmark metrics.