pub fn physical_core_count() -> usize {
#[cfg(target_os = "linux")]
if let Some(n) = linux_physical_cores() {
return n;
}
let ret = unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) };
if ret < 1 { 1 } else { ret as usize }
}
#[cfg(target_os = "linux")]
fn linux_physical_cores() -> Option<usize> {
use std::collections::HashSet;
let mut seen: HashSet<(String, String)> = HashSet::new();
let mut cpu = 0usize;
while let Ok(pkg_raw) = std::fs::read_to_string(format!(
"/sys/devices/system/cpu/cpu{cpu}/topology/physical_package_id"
)) {
let pkg = pkg_raw.trim().to_owned();
let core = match std::fs::read_to_string(format!(
"/sys/devices/system/cpu/cpu{cpu}/topology/core_id"
)) {
Ok(s) => s.trim().to_owned(),
Err(_) => break,
};
seen.insert((pkg, core));
cpu += 1;
}
if seen.is_empty() {
None
} else {
Some(seen.len())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn physical_core_count_is_positive() {
assert!(physical_core_count() >= 1);
}
#[test]
fn physical_core_count_does_not_exceed_logical() {
let logical = unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } as usize;
assert!(physical_core_count() <= logical);
}
}