@@ -62,3 +62,45 @@ pub fn get_working_perf_executable() -> Option<OsString> {
6262 debug ! ( "perf is installed but not functioning correctly" ) ;
6363 None
6464}
65+
66+ /// Detects if the required perf events are available on this system.
67+ /// Returns the flags to pass to perf record command if they are available, otherwise returns None.
68+ pub fn get_event_flags ( perf_executable : & OsString ) -> anyhow:: Result < Option < String > > {
69+ const CYCLES_EVENT_NAME : & str = "cycles" ;
70+ const CACHE_REFERENCES_EVENT_NAME : & str = "cache-references" ;
71+ const CACHE_MISSES_EVENT_NAME : & str = "cache-misses" ;
72+
73+ let perf_events = [
74+ CYCLES_EVENT_NAME ,
75+ CACHE_REFERENCES_EVENT_NAME ,
76+ CACHE_MISSES_EVENT_NAME ,
77+ ] ;
78+
79+ let output = Command :: new ( perf_executable)
80+ . arg ( "list" )
81+ . output ( )
82+ . context ( "Failed to run perf list" ) ?;
83+
84+ let stdout = String :: from_utf8_lossy ( & output. stdout ) ;
85+
86+ // Check if all required events are available
87+ let missing_events: Vec < & str > = perf_events
88+ . iter ( )
89+ . filter ( |& & event| !stdout. lines ( ) . any ( |line| line. trim ( ) . starts_with ( event) ) )
90+ . copied ( )
91+ . collect ( ) ;
92+
93+ if !missing_events. is_empty ( ) {
94+ debug ! (
95+ "Not all required perf events available. Missing: [{}], using default events" ,
96+ missing_events. join( ", " )
97+ ) ;
98+ return Ok ( None ) ;
99+ }
100+
101+ debug ! (
102+ "All required perf events available: {}" ,
103+ perf_events. join( ", " )
104+ ) ;
105+ Ok ( Some ( format ! ( "-e {{{}}}" , perf_events. join( "," ) ) ) )
106+ }
0 commit comments