diff options
Diffstat (limited to 'src/apple_silicon/src')
| -rw-r--r-- | src/apple_silicon/src/error.rs | 23 | ||||
| -rw-r--r-- | src/apple_silicon/src/main.rs | 10 | ||||
| -rw-r--r-- | src/apple_silicon/src/soc.rs | 75 |
3 files changed, 108 insertions, 0 deletions
diff --git a/src/apple_silicon/src/error.rs b/src/apple_silicon/src/error.rs new file mode 100644 index 0000000..a70b9b5 --- /dev/null +++ b/src/apple_silicon/src/error.rs @@ -0,0 +1,23 @@ +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("socinfo parsing error: `{0}`")] + Parse(String), + + #[error("I/O error: `{source}`")] + Io { + #[from] + source: std::io::Error, + }, + + #[error("utf8 conversion error: `{source}`")] + Utf8Conversion { + #[from] + source: std::string::FromUtf8Error, + }, + + #[error("integer parsing error: `{source}`")] + ParseInt { + #[from] + source: std::num::ParseIntError, + }, +} diff --git a/src/apple_silicon/src/main.rs b/src/apple_silicon/src/main.rs new file mode 100644 index 0000000..b54c3ec --- /dev/null +++ b/src/apple_silicon/src/main.rs @@ -0,0 +1,10 @@ +mod error; +mod soc; + +fn main() { + let cpu_info = soc::SocInfo::new().unwrap(); + println!( + "our CPU is an {}, and we have {} cores, and {} GPU cores", + cpu_info.cpu_brand_name, cpu_info.num_cpu_cores, cpu_info.num_gpu_cores, + ); +} diff --git a/src/apple_silicon/src/soc.rs b/src/apple_silicon/src/soc.rs new file mode 100644 index 0000000..fcf3ed3 --- /dev/null +++ b/src/apple_silicon/src/soc.rs @@ -0,0 +1,75 @@ +use crate::error::Error; + +use std::process::Command; + +pub type Result<T> = std::result::Result<T, Error>; + +pub struct SocInfo { + pub cpu_brand_name: String, + pub num_cpu_cores: u16, + pub num_gpu_cores: u16, +} + +impl SocInfo { + pub fn new() -> Result<SocInfo> { + let (cpu_brand_name, num_cpu_cores) = cpu_info()?; + + let num_gpu_cores = gpu_info()?; + + Ok(SocInfo { + cpu_brand_name, + num_cpu_cores, + num_gpu_cores, + }) + } +} + +// https://github.com/tlkh/asitop/blob/74ebe2cbc23d5b1eec874aebb1b9bacfe0e670cd/asitop/utils.py#L94 +fn cpu_info() -> Result<(String, u16)> { + let binary = "/usr/sbin/sysctl"; + let args = &[ + // don't display the variable name + "-n", + "machdep.cpu.brand_string", + "machdep.cpu.core_count", + ]; + + let output = Command::new(binary).args(args).output()?; + let buffer = String::from_utf8(output.stdout)?; + + let mut iter = buffer.split('\n'); + let cpu_brand_name = match iter.next() { + Some(s) => s.to_string(), + None => return Err(Error::Parse(buffer.to_string())), + }; + + let num_cpu_cores = match iter.next() { + Some(s) => s.parse::<u16>()?, + None => return Err(Error::Parse(buffer.to_string())), + }; + + Ok((cpu_brand_name, num_cpu_cores)) +} + +// https://github.com/tlkh/asitop/blob/74ebe2cbc23d5b1eec874aebb1b9bacfe0e670cd/asitop/utils.py#L120 +fn gpu_info() -> Result<u16> { + let binary = "/usr/sbin/system_profiler"; + let args = &["-detailLevel", "basic", "SPDisplaysDataType"]; + + let output = Command::new(binary).args(args).output()?; + let buffer = String::from_utf8(output.stdout)?; + + let num_gpu_cores_line = buffer + .lines() + .find(|&line| line.trim_start().starts_with("Total Number of Cores")); + + let num_gpu_cores = match num_gpu_cores_line { + Some(s) => match s.split(": ").last() { + Some(s) => s.parse::<u16>()?, + None => return Err(Error::Parse(buffer.to_string())), + }, + None => return Err(Error::Parse(buffer.to_string())), + }; + + Ok(num_gpu_cores) +} |
