@@ -4,12 +4,14 @@ use perf_event::events::Hardware;
44use perf_event:: { Builder , Counter , Group } ;
55use std:: time:: Instant ;
66
7+ /// A collection of CPU performance counters.
8+ /// The counters are optional, because some CPUs are not able to record them.
79struct Counters {
8- cycles : Counter ,
9- instructions : Counter ,
10- branch_misses : Counter ,
11- cache_misses : Counter ,
12- cache_references : Counter ,
10+ cycles : Option < Counter > ,
11+ instructions : Option < Counter > ,
12+ branch_misses : Option < Counter > ,
13+ cache_misses : Option < Counter > ,
14+ cache_references : Option < Counter > ,
1315}
1416
1517/// Benchmarks a single function generated by `benchmark_constructor`.
@@ -48,11 +50,11 @@ pub fn benchmark_function<F: Fn() -> Bench + 'static, R, Bench: FnOnce() -> R +
4850 black_box ( output) ;
4951
5052 let result = BenchmarkStats {
51- cycles : measurement [ & counters. cycles ] ,
52- instructions : measurement [ & counters. instructions ] ,
53- branch_misses : measurement [ & counters. branch_misses ] ,
54- cache_misses : measurement [ & counters. cache_misses ] ,
55- cache_references : measurement [ & counters. cache_references ] ,
53+ cycles : counters. cycles . map ( |c| measurement [ & c ] ) ,
54+ instructions : counters. instructions . map ( |c| measurement [ & c ] ) ,
55+ branch_misses : counters. branch_misses . map ( |c| measurement [ & c ] ) ,
56+ cache_misses : counters. cache_misses . map ( |c| measurement [ & c ] ) ,
57+ cache_references : counters. cache_references . map ( |c| measurement [ & c ] ) ,
5658 wall_time : duration,
5759 } ;
5860 Ok ( result)
@@ -77,19 +79,23 @@ Try lowering it with `sudo bash -c 'echo -1 > /proc/sys/kernel/perf_event_parano
7779}
7880
7981fn prepare_counters ( group : & mut Group ) -> anyhow:: Result < Counters > {
80- let mut add_event = |event : Hardware | {
81- Builder :: new ( )
82- . group ( group)
83- . kind ( event)
84- . build ( )
85- . map_err ( |error| anyhow:: anyhow!( "Could not add counter {:?}: {:?}" , event, error) )
82+ let mut add_event = |event : Hardware | match Builder :: new ( ) . group ( group) . kind ( event) . build ( ) {
83+ Ok ( counter) => Some ( counter) ,
84+ Err ( error) => {
85+ log:: warn!(
86+ "Could not add counter {:?}: {:?}. Maybe the CPU doesn't support it?" ,
87+ event,
88+ error
89+ ) ;
90+ None
91+ }
8692 } ;
8793
88- let cycles = add_event ( Hardware :: CPU_CYCLES ) ? ;
89- let instructions = add_event ( Hardware :: INSTRUCTIONS ) ? ;
90- let branch_misses = add_event ( Hardware :: BRANCH_MISSES ) ? ;
91- let cache_misses = add_event ( Hardware :: CACHE_MISSES ) ? ;
92- let cache_references = add_event ( Hardware :: CACHE_REFERENCES ) ? ;
94+ let cycles = add_event ( Hardware :: CPU_CYCLES ) ;
95+ let instructions = add_event ( Hardware :: INSTRUCTIONS ) ;
96+ let branch_misses = add_event ( Hardware :: BRANCH_MISSES ) ;
97+ let cache_misses = add_event ( Hardware :: CACHE_MISSES ) ;
98+ let cache_references = add_event ( Hardware :: CACHE_REFERENCES ) ;
9399
94100 Ok ( Counters {
95101 cycles,
0 commit comments