Skip to content

Commit d1b5721

Browse files
feat: add more events to perf monitoring
1 parent e954d5f commit d1b5721

2 files changed

Lines changed: 48 additions & 1 deletion

File tree

src/executor/wall_time/perf/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use crate::run::UnwindingMode;
1818
use anyhow::Context;
1919
use fifo::PerfFifo;
2020
use libc::pid_t;
21+
use perf_executable::get_event_flags;
2122
use perf_map::ProcessSymbols;
2223
use runner_shared::artifacts::ArtifactExt;
2324
use runner_shared::artifacts::ExecutionTimestamps;
@@ -131,11 +132,15 @@ impl PerfRunner {
131132

132133
let working_perf_executable =
133134
get_working_perf_executable().context("Failed to find a working perf executable")?;
134-
let mut perf_wrapper_builder = CommandBuilder::new(working_perf_executable);
135+
let mut perf_wrapper_builder = CommandBuilder::new(&working_perf_executable);
135136
perf_wrapper_builder.arg("record");
136137
if !is_codspeed_debug_enabled() {
137138
perf_wrapper_builder.arg("--quiet");
138139
}
140+
// Add events flag if all required events are available
141+
if let Some(events_flag) = get_event_flags(&working_perf_executable)? {
142+
perf_wrapper_builder.arg(events_flag);
143+
}
139144
perf_wrapper_builder.args([
140145
"--timestamp",
141146
// Required for matching the markers and URIs to the samples.

src/executor/wall_time/perf/perf_executable.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)