diff options
| author | Franck Cuny <franck@fcuny.net> | 2024-07-09 18:04:08 -0700 |
|---|---|---|
| committer | Franck Cuny <franck@fcuny.net> | 2024-07-09 18:04:08 -0700 |
| commit | d45e9b8c293fa1e04ede47af0007bc720f093413 (patch) | |
| tree | c1b27300f6e945c69360a1e23edad176af41673e | |
| download | x-d45e9b8c293fa1e04ede47af0007bc720f093413.tar.gz | |
initial commit
```
[18:04] mba-fcuny:apple_silicon (main +) | cargo run
Compiling apple_silicon v0.1.0 (/Users/fcuny/workspace/apple_silicon)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.13s
Running `target/debug/apple_silicon`
our CPU is an Apple M2, and we have 8 cores, and 10 GPU cores
```
| -rw-r--r-- | src/apple_silicon/.gitignore | 1 | ||||
| -rw-r--r-- | src/apple_silicon/Cargo.lock | 65 | ||||
| -rw-r--r-- | src/apple_silicon/Cargo.toml | 7 | ||||
| -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 |
6 files changed, 181 insertions, 0 deletions
diff --git a/src/apple_silicon/.gitignore b/src/apple_silicon/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/src/apple_silicon/.gitignore @@ -0,0 +1 @@ +/target diff --git a/src/apple_silicon/Cargo.lock b/src/apple_silicon/Cargo.lock new file mode 100644 index 0000000..25e57f9 --- /dev/null +++ b/src/apple_silicon/Cargo.lock @@ -0,0 +1,65 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "apple_silicon" +version = "0.1.0" +dependencies = [ + "thiserror", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201fcda3845c23e8212cd466bfebf0bd20694490fc0356ae8e428e0824a915a6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff --git a/src/apple_silicon/Cargo.toml b/src/apple_silicon/Cargo.toml new file mode 100644 index 0000000..21b6242 --- /dev/null +++ b/src/apple_silicon/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "apple_silicon" +version = "0.1.0" +edition = "2021" + +[dependencies] +thiserror = "1.0.61" 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) +} |
