use core_affinity::CoreId;
#[cfg(target_os = "linux")]
pub fn get_physical_cores() -> Vec<usize> {
use std::collections::HashMap;
use std::fs;
let mut sibling_map: HashMap<Vec<usize>, Vec<usize>> = HashMap::new();
if let Ok(entries) = fs::read_dir("/sys/devices/system/cpu") {
for entry in entries.flatten() {
let path = entry.path();
if let Some(name) = path.file_name().and_then(|n| n.to_str()) {
if name.starts_with("cpu") && name[3..].parse::<usize>().is_ok() {
let sibling_path = path.join("topology/thread_siblings_list");
if let Ok(content) = fs::read_to_string(&sibling_path) {
let mut siblings: Vec<usize> = content
.trim()
.split(',')
.filter_map(|s| s.parse().ok())
.collect();
siblings.sort_unstable();
if !siblings.is_empty() {
let cpu: usize = name[3..].parse().unwrap();
sibling_map.entry(siblings).or_default().push(cpu);
}
}
}
}
}
}
let mut physical: Vec<usize> = sibling_map
.values()
.filter_map(|group| group.iter().min().copied())
.collect();
physical.sort_unstable();
physical.dedup();
physical
}
#[cfg(target_os = "macos")]
pub fn get_physical_cores() -> Vec<usize> {
use std::process::Command;
let output = Command::new("sysctl")
.arg("-n")
.arg("hw.perflevel0.physicalcpu")
.output();
if let Ok(output) = output {
if let Ok(count_str) = std::str::from_utf8(&output.stdout) {
if let Ok(count) = count_str.trim().parse::<usize>() {
return (0..count).collect();
}
}
}
core_affinity::get_core_ids()
.unwrap_or_default()
.into_iter()
.map(|id| id.id)
.collect()
}
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
pub fn get_physical_cores() -> Vec<usize> {
core_affinity::get_core_ids()
.unwrap_or_default()
.into_iter()
.map(|id| id.id)
.collect()
}
pub fn pin_to_physical_core() -> bool {
let physical_cores = get_physical_cores();
if !physical_cores.is_empty() {
core_affinity::set_for_current(CoreId {
id: physical_cores[0],
})
} else {
false
}
}
pub fn pin_to_core(core_idx: usize) -> bool {
let physical_cores = get_physical_cores();
if core_idx < physical_cores.len() {
core_affinity::set_for_current(CoreId {
id: physical_cores[core_idx],
})
} else {
false
}
}
pub fn num_physical_cores() -> usize {
get_physical_cores().len()
}