#[cfg(target_os = "macos")]
use super::super::capabilities::PlatformCapabilities;
#[cfg(any(test, target_os = "macos"))]
use super::super::capabilities::Support;
#[cfg(target_os = "macos")]
use super::super::contract::{AcceleratorBackend, TelemetryBackend};
#[cfg(any(test, target_os = "macos"))]
use super::super::profile::{AcceleratorInfo, AcceleratorKind, MemoryModelKind};
#[cfg(target_os = "macos")]
use super::super::profile::{CpuProfile, HostProfile, MemoryProfile};
#[cfg(target_os = "macos")]
use super::super::run;
#[cfg(any(test, target_os = "macos"))]
use crate::os::monitor::GpuSnapshot;
#[cfg(target_os = "macos")]
use anyhow::Result;
#[cfg(target_os = "macos")]
pub struct Backend;
#[cfg(target_os = "macos")]
impl TelemetryBackend for Backend {
fn host_profile(&self) -> Result<HostProfile> {
Ok(HostProfile {
schema_version: 1,
os: std::env::consts::OS.into(),
arch: std::env::consts::ARCH.into(),
cpu: cpu_profile(),
memory: memory_profile(),
accelerators: accelerator_info(),
capabilities: capabilities(),
})
}
}
#[cfg(target_os = "macos")]
impl AcceleratorBackend for Backend {
fn accelerators(&self) -> Result<Vec<AcceleratorInfo>> {
Ok(accelerator_info())
}
}
#[cfg(target_os = "macos")]
fn cpu_profile() -> CpuProfile {
let logical_cores = run("sysctl", &["-n", "hw.logicalcpu"])
.ok()
.filter(|o| o.success)
.and_then(|o| o.stdout.trim().parse().ok())
.unwrap_or_else(|| std::thread::available_parallelism().map_or(1, usize::from));
let physical_cores = run("sysctl", &["-n", "hw.physicalcpu"])
.ok()
.filter(|o| o.success)
.and_then(|o| o.stdout.trim().parse().ok());
let vendor = run("sysctl", &["-n", "machdep.cpu.brand_string"])
.ok()
.filter(|o| o.success)
.map(|o| o.stdout.trim().to_string())
.filter(|value| !value.is_empty());
CpuProfile {
logical_cores,
physical_cores,
vendor,
}
}
#[cfg(target_os = "macos")]
fn memory_profile() -> MemoryProfile {
let total_bytes = run("sysctl", &["-n", "hw.memsize"])
.ok()
.filter(|o| o.success)
.and_then(|o| o.stdout.trim().parse().ok());
let model = if std::env::consts::ARCH == "aarch64" {
MemoryModelKind::Unified
} else {
MemoryModelKind::Unknown
};
MemoryProfile { total_bytes, model }
}
#[cfg(target_os = "macos")]
fn accelerator_info() -> Vec<AcceleratorInfo> {
super::telemetry::collect_gpus(&mut Vec::new())
.into_iter()
.map(classify_gpu)
.collect()
}
#[cfg(any(test, target_os = "macos"))]
fn classify_gpu(gpu: GpuSnapshot) -> AcceleratorInfo {
let is_nvidia = gpu.source == "nvidia-smi";
let is_apple = gpu.vendor.as_deref().is_some_and(|v| v.contains("Apple"));
let memory_model = if is_apple {
MemoryModelKind::Unified
} else if is_nvidia {
MemoryModelKind::Dedicated
} else {
MemoryModelKind::Unknown
};
let dedicated_memory_bytes = (memory_model == MemoryModelKind::Dedicated)
.then_some(gpu.memory_total_bytes)
.flatten();
AcceleratorInfo {
kind: AcceleratorKind::Gpu,
vendor: if is_apple {
Some("Apple".into())
} else {
gpu.vendor
},
name: gpu.name,
backend: if is_apple {
Some("metal".into())
} else if is_nvidia {
Some("cuda".into())
} else {
None
},
memory_model,
dedicated_memory_bytes,
telemetry: if gpu.status == "ready" {
Support::Supported
} else {
Support::Unsupported
},
}
}
#[cfg(test)]
mod tests {
use super::*;
fn sample_gpu(vendor: &str, source: &str, status: &str) -> GpuSnapshot {
GpuSnapshot {
name: "Test GPU".into(),
vendor: Some(vendor.into()),
utilization_percent: None,
memory_total_bytes: Some(16 * 1024u64.pow(3)),
memory_used_bytes: None,
source: source.into(),
status: status.into(),
}
}
#[test]
fn real_system_profiler_apple_vendor_string_is_recognized() {
let info = classify_gpu(sample_gpu(
"sppci_vendor_Apple",
"system_profiler",
"inventory-only",
));
assert_eq!(info.vendor.as_deref(), Some("Apple"));
assert_eq!(info.memory_model, MemoryModelKind::Unified);
assert_eq!(info.backend.as_deref(), Some("metal"));
assert_eq!(info.dedicated_memory_bytes, None);
assert_eq!(info.telemetry, Support::Unsupported);
}
#[test]
fn nvidia_via_smi_is_dedicated_cuda_and_has_live_telemetry() {
let info = classify_gpu(sample_gpu("NVIDIA", "nvidia-smi", "ready"));
assert_eq!(info.memory_model, MemoryModelKind::Dedicated);
assert_eq!(info.backend.as_deref(), Some("cuda"));
assert_eq!(info.dedicated_memory_bytes, Some(16 * 1024u64.pow(3)));
assert_eq!(info.telemetry, Support::Supported);
}
#[test]
fn unrecognized_vendor_stays_unknown_not_guessed() {
let info = classify_gpu(sample_gpu(
"Intel(R) UHD",
"system_profiler",
"inventory-only",
));
assert_eq!(info.memory_model, MemoryModelKind::Unknown);
assert_eq!(info.backend, None);
assert_eq!(info.dedicated_memory_bytes, None);
}
}
#[cfg(target_os = "macos")]
fn capabilities() -> PlatformCapabilities {
PlatformCapabilities {
native_service_manager: Support::Supported,
filesystem_events: Support::Supported,
secure_secret_storage: Support::Supported,
process_containment: Support::Supported,
native_notifications: Support::Supported,
accelerator_telemetry: Support::Unknown,
}
}