@@ -5,23 +5,25 @@ use crate::measure::benchmark_function;
55use crate :: process:: raise_process_priority;
66use std:: collections:: HashMap ;
77
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+ {
1014 env_logger:: init ( ) ;
1115
1216 let mut group = BenchmarkGroup :: new ( ) ;
13- define_func ( & mut group) ;
17+ register ( & mut group) ;
1418 group. run ( ) . expect ( "Benchmark group execution has failed" ) ;
1519}
1620
1721/// 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 > > ;
2123
2224#[ derive( Default ) ]
2325pub struct BenchmarkGroup {
24- benchmarks : HashMap < & ' static str , BenchmarkWrapper > ,
26+ benchmarks : HashMap < & ' static str , BenchmarkFn > ,
2527}
2628
2729impl BenchmarkGroup {
@@ -30,19 +32,21 @@ impl BenchmarkGroup {
3032 }
3133
3234 /// 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+ {
3946 // 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) ;
4650 }
4751 }
4852
@@ -63,7 +67,7 @@ impl BenchmarkGroup {
6367 }
6468
6569 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
6771 . benchmarks
6872 . into_iter ( )
6973 . filter ( |( name, _) | {
@@ -74,10 +78,10 @@ impl BenchmarkGroup {
7478
7579 let mut stdout = std:: io:: stdout ( ) . lock ( ) ;
7680
77- for ( name, def ) in items {
81+ for ( name, benchmark_fn ) in items {
7882 let mut stats: Vec < BenchmarkStats > = Vec :: with_capacity ( args. iterations as usize ) ;
7983 for i in 0 ..args. iterations {
80- let benchmark_stats = ( def . func ) ( ) ?;
84+ let benchmark_stats = benchmark_fn ( ) ?;
8185 log:: info!( "Benchmark (run {i}) `{name}` completed: {benchmark_stats:?}" ) ;
8286 stats. push ( benchmark_stats) ;
8387 }
@@ -101,24 +105,6 @@ impl BenchmarkGroup {
101105 }
102106}
103107
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-
122108/// Tests if the name of the benchmark passes through the include and exclude filters.
123109/// Both filters can contain multiple comma-separated prefixes.
124110pub fn passes_filter ( name : & str , exclude : Option < & str > , include : Option < & str > ) -> bool {
0 commit comments