@@ -12,33 +12,42 @@ struct Counters {
12
12
cache_references : Counter ,
13
13
}
14
14
15
- /// Benchmarks a single function.
16
- pub fn benchmark_function < F : FnOnce ( ) -> R , R > (
15
+ /// Benchmarks a single function generated by `benchmark_constructor`.
16
+ /// The function is executed twice, once to gather wall-time measurement and the second time to
17
+ /// gather perf. counters.
18
+ pub fn benchmark_function < F : Fn ( ) -> Bench + ' static , R , Bench : FnOnce ( ) -> R + ' static > (
17
19
name : & ' static str ,
18
- func : F ,
20
+ benchmark_constructor : F ,
19
21
) -> anyhow:: Result < BenchmarkResult > {
20
22
let mut group = create_group ( ) ?;
21
23
let counters = prepare_counters ( & mut group) ?;
22
24
23
- // FIXME: don't run perf counters and time measurements together, run the benchmark twice
24
- // instead.
25
- let start = Instant :: now ( ) ;
25
+ // Measure perf. counters.
26
+ let func = benchmark_constructor ( ) ;
26
27
27
28
// Do not act on the return value to avoid including the branch in the measurement
28
29
let enable_ret = group. enable ( ) ;
29
30
let output = func ( ) ;
30
31
group. disable ( ) ?;
31
32
32
- let duration = start. elapsed ( ) ;
33
+ // Try to avoid optimizing the result out.
34
+ black_box ( output) ;
33
35
34
36
// Check if we have succeeded before
35
37
enable_ret?;
36
38
37
- // Try to avoid optimizing the result out
38
- black_box ( output) ;
39
-
40
39
let measurement = group. read ( ) ?;
41
40
41
+ // Measure wall time.
42
+ let func = benchmark_constructor ( ) ;
43
+
44
+ let start = Instant :: now ( ) ;
45
+ let output = func ( ) ;
46
+ let duration = start. elapsed ( ) ;
47
+
48
+ // Try to avoid optimizing the result out.
49
+ black_box ( output) ;
50
+
42
51
let result = BenchmarkResult {
43
52
name : String :: from ( name) ,
44
53
cycles : measurement[ & counters. cycles ] ,
0 commit comments