aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFranck Cuny <franck@fcuny.net>2024-07-09 18:04:08 -0700
committerFranck Cuny <franck@fcuny.net>2024-07-09 18:04:08 -0700
commitd45e9b8c293fa1e04ede47af0007bc720f093413 (patch)
treec1b27300f6e945c69360a1e23edad176af41673e /src
downloadx-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 ```
Diffstat (limited to 'src')
-rw-r--r--src/apple_silicon/.gitignore1
-rw-r--r--src/apple_silicon/Cargo.lock65
-rw-r--r--src/apple_silicon/Cargo.toml7
-rw-r--r--src/apple_silicon/src/error.rs23
-rw-r--r--src/apple_silicon/src/main.rs10
-rw-r--r--src/apple_silicon/src/soc.rs75
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)
+}