@@ -5,23 +5,25 @@ use crate::measure::benchmark_function;
5
5
use crate :: process:: raise_process_priority;
6
6
use std:: collections:: HashMap ;
7
7
8
- /// Create a new benchmark group. Use the closure argument to define individual benchmarks.
9
- pub fn run_benchmark_group < F : FnOnce ( & mut BenchmarkGroup ) > ( define_func : F ) {
8
+ /// Create and run a new benchmark group. Use the closure argument to register
9
+ /// the individual benchmarks.
10
+ pub fn run_benchmark_group < F > ( register : F )
11
+ where
12
+ F : FnOnce ( & mut BenchmarkGroup ) ,
13
+ {
10
14
env_logger:: init ( ) ;
11
15
12
16
let mut group = BenchmarkGroup :: new ( ) ;
13
- define_func ( & mut group) ;
17
+ register ( & mut group) ;
14
18
group. run ( ) . expect ( "Benchmark group execution has failed" ) ;
15
19
}
16
20
17
21
/// Type-erased function that executes a single benchmark.
18
- struct BenchmarkWrapper {
19
- func : Box < dyn Fn ( ) -> anyhow:: Result < BenchmarkStats > > ,
20
- }
22
+ type BenchmarkFn = Box < dyn Fn ( ) -> anyhow:: Result < BenchmarkStats > > ;
21
23
22
24
#[ derive( Default ) ]
23
25
pub struct BenchmarkGroup {
24
- benchmarks : HashMap < & ' static str , BenchmarkWrapper > ,
26
+ benchmarks : HashMap < & ' static str , BenchmarkFn > ,
25
27
}
26
28
27
29
impl BenchmarkGroup {
@@ -30,19 +32,21 @@ impl BenchmarkGroup {
30
32
}
31
33
32
34
/// Registers a single benchmark.
33
- /// `constructor` should return a closure that will be benchmarked.
34
- pub fn register < F : Fn ( ) -> Bench + Clone + ' static , R , Bench : FnOnce ( ) -> R + ' static > (
35
- & mut self ,
36
- name : & ' static str ,
37
- constructor : F ,
38
- ) {
35
+ ///
36
+ /// `constructor` returns a closure that will be benchmarked. This means
37
+ /// `constructor` can do initialization steps outside of the code that is
38
+ /// measured. `constructor` may be called multiple times (e.g. once for a
39
+ /// run with performance counters and once for a run without), but the
40
+ /// closure it produces each time will only be called once.
41
+ pub fn register_benchmark < Ctor , Bench , R > ( & mut self , name : & ' static str , constructor : Ctor )
42
+ where
43
+ Ctor : Fn ( ) -> Bench + Clone + ' static ,
44
+ Bench : FnOnce ( ) -> R + ' static ,
45
+ {
39
46
// We want to type-erase the target `func` by wrapping it in a Box.
40
- let benchmark_func = Box :: new ( move || benchmark_function ( constructor. clone ( ) ) ) ;
41
- let benchmark_def = BenchmarkWrapper {
42
- func : benchmark_func,
43
- } ;
44
- if self . benchmarks . insert ( name, benchmark_def) . is_some ( ) {
45
- panic ! ( "Benchmark {} was registered twice" , name) ;
47
+ let benchmark_fn = Box :: new ( move || benchmark_function ( constructor. clone ( ) ) ) ;
48
+ if self . benchmarks . insert ( name, benchmark_fn) . is_some ( ) {
49
+ panic ! ( "Benchmark '{}' was registered twice" , name) ;
46
50
}
47
51
}
48
52
@@ -63,7 +67,7 @@ impl BenchmarkGroup {
63
67
}
64
68
65
69
fn run_benchmarks ( self , args : BenchmarkArgs ) -> anyhow:: Result < ( ) > {
66
- let mut items: Vec < ( & ' static str , BenchmarkWrapper ) > = self
70
+ let mut items: Vec < ( & ' static str , BenchmarkFn ) > = self
67
71
. benchmarks
68
72
. into_iter ( )
69
73
. filter ( |( name, _) | {
@@ -74,10 +78,10 @@ impl BenchmarkGroup {
74
78
75
79
let mut stdout = std:: io:: stdout ( ) . lock ( ) ;
76
80
77
- for ( name, def ) in items {
81
+ for ( name, benchmark_fn ) in items {
78
82
let mut stats: Vec < BenchmarkStats > = Vec :: with_capacity ( args. iterations as usize ) ;
79
83
for i in 0 ..args. iterations {
80
- let benchmark_stats = ( def . func ) ( ) ?;
84
+ let benchmark_stats = benchmark_fn ( ) ?;
81
85
log:: info!( "Benchmark (run {i}) `{name}` completed: {benchmark_stats:?}" ) ;
82
86
stats. push ( benchmark_stats) ;
83
87
}
@@ -101,24 +105,6 @@ impl BenchmarkGroup {
101
105
}
102
106
}
103
107
104
- /// Adds a single benchmark to the benchmark group.
105
- /// ```ignore
106
- /// use benchlib::define_benchmark;
107
- ///
108
- /// define_benchmark!(group, my_bench, {
109
- /// || do_something()
110
- /// });
111
- /// ```
112
- #[ macro_export]
113
- macro_rules! define_benchmark {
114
- ( $group: expr, $name: ident, $fun: expr) => {
115
- let func = move || $fun;
116
- $group. register( stringify!( $name) , func) ;
117
- } ;
118
- }
119
-
120
- pub use define_benchmark;
121
-
122
108
/// Tests if the name of the benchmark passes through the include and exclude filters.
123
109
/// Both filters can contain multiple comma-separated prefixes.
124
110
pub fn passes_filter ( name : & str , exclude : Option < & str > , include : Option < & str > ) -> bool {
0 commit comments