use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct AppleSiliconInfo {
pub chip: String,
pub p_cores: u32,
pub e_cores: u32,
pub gpu_cores: u32,
pub neural_cores: u32,
pub unified_memory_bytes: u64,
}
impl AppleSiliconInfo {
pub fn new(chip: impl Into<String>) -> Self {
Self {
chip: chip.into(),
p_cores: 0,
e_cores: 0,
gpu_cores: 0,
neural_cores: 16, unified_memory_bytes: 0,
}
}
pub fn with_cores(mut self, p_cores: u32, e_cores: u32, gpu_cores: u32) -> Self {
self.p_cores = p_cores;
self.e_cores = e_cores;
self.gpu_cores = gpu_cores;
self
}
pub fn with_memory(mut self, bytes: u64) -> Self {
self.unified_memory_bytes = bytes;
self
}
pub fn total_cpu_cores(&self) -> u32 {
self.p_cores + self.e_cores
}
pub fn unified_memory_gb(&self) -> f64 {
self.unified_memory_bytes as f64 / (1024.0 * 1024.0 * 1024.0)
}
#[cfg(target_os = "macos")]
pub fn detect() -> Option<Self> {
let arch = std::env::consts::ARCH;
if arch != "aarch64" {
return None;
}
let chip = std::process::Command::new("sysctl")
.args(["-n", "machdep.cpu.brand_string"])
.output()
.ok()
.and_then(|output| String::from_utf8(output.stdout).ok())
.map(|s| s.trim().to_string())
.unwrap_or_else(|| "Apple Silicon".to_string());
let p_cores = std::process::Command::new("sysctl")
.args(["-n", "hw.perflevel0.logicalcpu"])
.output()
.ok()
.and_then(|output| String::from_utf8(output.stdout).ok())
.and_then(|s| s.trim().parse().ok())
.unwrap_or(0);
let e_cores = std::process::Command::new("sysctl")
.args(["-n", "hw.perflevel1.logicalcpu"])
.output()
.ok()
.and_then(|output| String::from_utf8(output.stdout).ok())
.and_then(|s| s.trim().parse().ok())
.unwrap_or(0);
let memory = std::process::Command::new("sysctl")
.args(["-n", "hw.memsize"])
.output()
.ok()
.and_then(|output| String::from_utf8(output.stdout).ok())
.and_then(|s| s.trim().parse().ok())
.unwrap_or(0);
Some(
Self::new(chip)
.with_cores(p_cores, e_cores, 0) .with_memory(memory),
)
}
#[cfg(not(target_os = "macos"))]
pub fn detect() -> Option<Self> {
None
}
}