1use criterion::{
2    criterion_group, criterion_main, Bencher, Criterion, Throughput,
3};
4
5mod data;
6mod memchr;
7mod memmem;
8
9fn all(c: &mut Criterion) {
10    memchr::all(c);
11    memmem::all(c);
12}
13
14/// A convenience function for defining a Criterion benchmark using our own
15/// conventions and a common config.
16///
17/// Note that we accept `bench` as a boxed closure to avoid the costs
18/// of monomorphization. Particularly with the memchr benchmarks, this
19/// function getting monomorphized (which also monomorphizes via Criterion's
20/// `bench_function`) bloats compile times dramatically (by an order of
21/// magnitude). This is okay to do since `bench` isn't the actual thing we
22/// measure. The measurement comes from running `Bencher::iter` from within`
23/// bench. So the dynamic dispatch is okay here.
24fn define(
25    c: &mut Criterion,
26    name: &str,
27    corpus: &[u8],
28    bench: Box<dyn FnMut(&mut Bencher<'_>) + 'static>,
29) {
30    // I don't really "get" the whole Criterion benchmark group thing. I just
31    // want a flat namespace to define all benchmarks. The only thing that
32    // matters to me is that we can group benchmarks arbitrarily using the
33    // name only. So we play Criterion's game by splitting our benchmark name
34    // on the first flash.
35    //
36    // N.B. We don't include the slash, since Criterion automatically adds it.
37    let mut it = name.splitn(2, "/");
38    let (group_name, bench_name) = (it.next().unwrap(), it.next().unwrap());
39    c.benchmark_group(group_name)
40        .throughput(Throughput::Bytes(corpus.len() as u64))
41        .sample_size(10)
42        .warm_up_time(std::time::Duration::from_millis(500))
43        .measurement_time(std::time::Duration::from_secs(2))
44        .bench_function(bench_name, bench);
45}
46
47criterion_group!(does_not_matter, all);
48criterion_main!(does_not_matter);
49