Skip to content

Commit a38f903

Browse files
committed
Added support for Performance / Efficency cores.
1 parent 8189bc7 commit a38f903

File tree

1 file changed

+60
-3
lines changed
  • collector/src/compile/execute

1 file changed

+60
-3
lines changed

collector/src/compile/execute/mod.rs

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,55 @@ pub struct CargoProcess<'a> {
129129
pub touch_file: Option<String>,
130130
pub jobserver: Option<jobserver::Client>,
131131
}
132-
132+
/// Returns an optional list of Performance CPU cores, if the system has P and E cores.
133+
/// This list *should* be in a format suitable for the `taskset` command.
134+
#[cfg(target_os = "linux")]
135+
fn performance_cores() -> Option<&'static String> {
136+
use std::sync::LazyLock;
137+
static PERFORMANCE_CORES: LazyLock<Option<String>> = LazyLock::new(|| {
138+
// Check if /sys/devices/cpu exists - if it does, then this is not a "Performance-hybrid" CPU.
139+
if std::fs::exists("/sys/devices/cpu").expect("Could not check the CPU architecture detali: could not check if `/sys/devices/cpu` exists!"){
140+
None
141+
}
142+
// Check if /sys/devices/cpu_core exists - if it does, then this is a "Performance-hybrid" CPU.
143+
else if std::fs::exists("/sys/devices/cpu_core").expect("Could not check the CPU architecture detali: could not check if `/sys/devices/cpu_core` exists!") {
144+
Some(std::fs::read_to_string("/sys/devices/cpu_core/cpus").unwrap().trim().to_string())
145+
}else{
146+
// If neither dir exists, then something is wrong - `/sys/devices/cpu` has been in Linux for over a decade.
147+
eprintln!("WARNING: neither `/sys/devices/cpu` nor `/sys/devices/cpu_core` present, unable to determine if this CPU has a Performance-Hybrid architecture.");
148+
None
149+
}
150+
});
151+
(*PERFORMANCE_CORES).as_ref()
152+
}
153+
#[cfg(target_os = "windows")]
154+
// Windows stub - TODO: implement to add Performance core support to Windows.
155+
fn performance_cores() -> Option<&'static String>{
156+
None
157+
}
158+
#[cfg(target_os = "macos")]
159+
// To my knoweladge, MacOS does not run on hardware with P/E cores, so this can simply always return None.
160+
fn performance_cores() -> Option<&'static String>{
161+
None
162+
}
163+
#[cfg(not(any(target_os = "windows",target_os = "macos",target_os = "linux")))]
164+
// I don't think rustc-perf runs on OSs other than Linux, Windows, or Mac, but I'll still leave a stub here just in case.
165+
fn performance_cores() -> Option<&'static String>{
166+
None
167+
}
168+
#[cfg(target_os = "linux")]
169+
/// Makes the benchmark run only on Performance cores.
170+
fn run_on_p_cores(path:&Path,cpu_list:&str)->Command{
171+
let mut cmd = Command::new("taskset");
172+
cmd.arg("--cpu-list");
173+
cmd.arg(cpu_list);
174+
cmd.arg(path);
175+
cmd
176+
}
177+
#[cfg(not(target_os = "linux"))]
178+
fn run_on_p_cores(path:&Path,cpu_list:&str)->Command{
179+
todo!("Can't run comamnds on the P cores on this platofmr")
180+
}
133181
impl<'a> CargoProcess<'a> {
134182
pub fn incremental(mut self, incremental: bool) -> Self {
135183
self.incremental = incremental;
@@ -148,7 +196,12 @@ impl<'a> CargoProcess<'a> {
148196
}
149197

150198
fn base_command(&self, cwd: &Path, subcommand: &str) -> Command {
151-
let mut cmd = Command::new(Path::new(&self.toolchain.components.cargo));
199+
// Processors with P and E cores require special handling
200+
let mut cmd = if let Some(p_cores) = performance_cores() {
201+
run_on_p_cores(Path::new(&self.toolchain.components.cargo),p_cores)
202+
} else{
203+
Command::new(Path::new(&self.toolchain.components.cargo))
204+
};
152205
cmd
153206
// Not all cargo invocations (e.g. `cargo clean`) need all of these
154207
// env vars set, but it doesn't hurt to have them.
@@ -551,7 +604,11 @@ fn process_stat_output(
551604
let mut parts = line.split(';').map(|s| s.trim());
552605
let cnt = get!(parts.next());
553606
let _unit = get!(parts.next());
554-
let name = get!(parts.next());
607+
let mut name = get!(parts.next());
608+
// Map P-core events to normal events
609+
if name == "cpu_core/instructions:u/"{
610+
name = "instructions:u".into();
611+
}
555612
let _time = get!(parts.next());
556613
let pct = get!(parts.next());
557614
if cnt == "<not supported>" || cnt == "<not counted>" || cnt.is_empty() {

0 commit comments

Comments
 (0)