Skip to content

Commit 3f70c22

Browse files
feat: add more events to perf monitoring
1 parent 2359e53 commit 3f70c22

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

src/run/runner/wall_time/perf/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use fifo::{PerfFifo, RunnerFifo};
1919
use libc::pid_t;
2020
use nix::sys::time::TimeValLike;
2121
use nix::time::clock_gettime;
22+
use perf_executable::get_event_flags;
2223
use perf_map::ProcessSymbols;
2324
use runner_shared::debug_info::ModuleDebugInfo;
2425
use runner_shared::fifo::Command as FifoCommand;
@@ -120,11 +121,15 @@ impl PerfRunner {
120121

121122
let working_perf_executable =
122123
get_working_perf_executable().context("Failed to find a working perf executable")?;
123-
let mut perf_wrapper_builder = CommandBuilder::new(working_perf_executable);
124+
let mut perf_wrapper_builder = CommandBuilder::new(&working_perf_executable);
124125
perf_wrapper_builder.arg("record");
125126
if !is_codspeed_debug_enabled() {
126127
perf_wrapper_builder.arg("--quiet");
127128
}
129+
// Add events flag if all required events are available
130+
if let Some(events_flag) = get_event_flags(&working_perf_executable)? {
131+
perf_wrapper_builder.arg(events_flag);
132+
}
128133
perf_wrapper_builder.args([
129134
"--timestamp",
130135
// Required for matching the markers and URIs to the samples.

src/run/runner/wall_time/perf/perf_executable.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,46 @@ 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 Some("-e {cycles,cache-references,cache-misses}") if all three events are available,
68+
/// None otherwise.
69+
pub fn get_event_flags(perf_executable: &OsString) -> anyhow::Result<Option<String>> {
70+
const CYCLES_EVENT_NAME: &str = "cycles";
71+
const CACHE_REFERENCES_EVENT_NAME: &str = "cache-references";
72+
const CACHE_MISSES_EVENT_NAME: &str = "cache-misses";
73+
74+
let perf_events = [
75+
CYCLES_EVENT_NAME,
76+
CACHE_REFERENCES_EVENT_NAME,
77+
CACHE_MISSES_EVENT_NAME,
78+
];
79+
80+
let output = Command::new(perf_executable)
81+
.arg("list")
82+
.output()
83+
.context("Failed to run perf list")?;
84+
85+
let stdout = String::from_utf8_lossy(&output.stdout);
86+
87+
// Check if all required events are available
88+
let missing_events: Vec<&str> = perf_events
89+
.iter()
90+
.filter(|&&event| !stdout.lines().any(|line| line.trim().starts_with(event)))
91+
.copied()
92+
.collect();
93+
94+
if !missing_events.is_empty() {
95+
debug!(
96+
"Not all required perf events available. Missing: [{}], using default events",
97+
missing_events.join(", ")
98+
);
99+
return Ok(None);
100+
}
101+
102+
debug!(
103+
"All required perf events available: {}",
104+
perf_events.join(", ")
105+
);
106+
Ok(Some(format!("-e {{{}}}", perf_events.join(","))))
107+
}

0 commit comments

Comments
 (0)