1use std::ffi::CString;
2
3use criterion::measurement::{Measurement, ValueFormatter};
4use libpapi_sys::*;
5
6mod formatter;
7use formatter::InsFormatter;
8
9pub struct PapiMeasurement {
10 event_set: std::os::raw::c_int,
11}
12
13impl PapiMeasurement {
14 pub fn new(event: &str) -> PapiMeasurement {
15 let mut event_set = PAPI_NULL;
16 let mut papi_tot_ins: std::os::raw::c_int = 0;
17
18 let event_name = CString::new(event).expect("CString::new failed");
19
20 unsafe {
21 let retval = PAPI_library_init(PAPI_VER_CURRENT);
22 if retval != PAPI_VER_CURRENT {
23 panic!("PAPI_library_init failed {}", retval)
24 }
25
26 let retval = PAPI_event_name_to_code(event_name.into_raw(), &mut papi_tot_ins);
27 if retval != PAPI_OK as i32 {
28 panic!("PAPI_event_name_to_code failed {}", retval)
29 }
30
31 let retval = PAPI_create_eventset(&mut event_set);
32 if retval != PAPI_OK as i32 {
33 panic!("PAPI_create_eventset error {}", retval)
34 }
35
36 let retval = PAPI_add_event(event_set.clone(), papi_tot_ins as i32);
37 if retval != PAPI_OK as i32 {
38 panic!("PAPI_add_event failed {}", retval)
39 }
40 }
41
42 return PapiMeasurement {
43 event_set,
44 }
45 }
46}
47
48impl Measurement for PapiMeasurement {
49 type Intermediate = i64;
50 type Value = i64;
51
52 fn start(&self) -> Self::Intermediate {
53 let mut values = [0i64];
54
55 unsafe {
56 let retval = PAPI_start(self.event_set.clone());
57 if retval != PAPI_OK as i32 {
58 panic!("PAPI_start failed {}", retval)
59 }
60
61 let retval = PAPI_read(self.event_set.clone(), values.as_mut_ptr());
62 if retval != PAPI_OK as i32 {
63 panic!("PAPI_read failed")
64 }
65 }
66
67 values[0]
68 }
69
70 fn end(&self, i: Self::Intermediate) -> Self::Value {
71 let mut values = [0i64];
72
73 unsafe {
74 let retval = PAPI_stop(self.event_set.clone(), values.as_mut_ptr());
75 if retval != PAPI_OK as i32 {
76 panic!("PAPI_read failed")
77 }
78 }
79
80 values[0] - i
81 }
82
83 fn add(&self, v1: &Self::Value, v2: &Self::Value) -> Self::Value {
84 v1 + v2
85 }
86
87 fn zero(&self) -> Self::Value {
88 0
89 }
90
91 fn to_f64(&self, value: &Self::Value) -> f64 {
92 *value as f64
93 }
94
95 fn formatter(&self) -> &dyn ValueFormatter {
96 &InsFormatter
97 }
98}