use super::capabilities::*;
use std::env;
pub fn detect_platform_capabilities() -> PlatformCapabilities {
PlatformCapabilities {
cpu: detect_cpu_capabilities(),
gpu: detect_gpu_capabilities(),
memory: detect_memory_capabilities(),
platform_type: detect_platform_type(),
os: detect_operating_system(),
architecture: detect_architecture(),
}
}
fn detect_cpu_capabilities() -> CpuCapabilities {
let logical_cores = num_cpus::get();
let physical_cores = num_cpus::get_physical();
CpuCapabilities {
physical_cores,
logical_cores,
simd: detect_simd_capabilities(),
cache: detect_cache_info(),
base_clock_mhz: detect_cpu_frequency(),
vendor: detect_cpu_vendor(),
model_name: detect_cpu_model(),
}
}
fn detect_cpu_frequency() -> Option<f32> {
use sysinfo::System;
let mut sys = System::new();
sys.refresh_cpu_all();
sys.cpus().first().map(|cpu| cpu.frequency() as f32)
}
fn detect_simd_capabilities() -> SimdCapabilities {
#[cfg(target_arch = "x86_64")]
{
SimdCapabilities {
sse: is_x86_feature_detected!("sse"),
sse2: is_x86_feature_detected!("sse2"),
sse3: is_x86_feature_detected!("sse3"),
ssse3: is_x86_feature_detected!("ssse3"),
sse4_1: is_x86_feature_detected!("sse4.1"),
sse4_2: is_x86_feature_detected!("sse4.2"),
avx: is_x86_feature_detected!("avx"),
avx2: is_x86_feature_detected!("avx2"),
avx512: cfg!(target_feature = "avx512f"),
fma: is_x86_feature_detected!("fma"),
neon: false,
sve: false,
}
}
#[cfg(target_arch = "aarch64")]
{
SimdCapabilities {
sse: false,
sse2: false,
sse3: false,
ssse3: false,
sse4_1: false,
sse4_2: false,
avx: false,
avx2: false,
avx512: false,
fma: false,
neon: cfg!(target_feature = "neon"),
sve: cfg!(target_feature = "sve"),
}
}
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
{
SimdCapabilities {
sse: false,
sse2: false,
sse3: false,
ssse3: false,
sse4_1: false,
sse4_2: false,
avx: false,
avx2: false,
avx512: false,
fma: false,
neon: false,
sve: false,
}
}
}
const fn detect_cache_info() -> CacheInfo {
CacheInfo {
l1_data: Some(32 * 1024), l1_instruction: Some(32 * 1024), l2: Some(256 * 1024), l3: Some(8 * 1024 * 1024), line_size: Some(64), }
}
fn detect_cpu_vendor() -> String {
use sysinfo::System;
let mut sys = System::new();
sys.refresh_cpu_all();
if let Some(cpu) = sys.cpus().first() {
let brand = cpu.brand();
if brand.contains("Intel") {
return "Intel".to_string();
} else if brand.contains("AMD") {
return "AMD".to_string();
} else if brand.contains("Apple") {
return "Apple".to_string();
} else if brand.contains("ARM") {
return "ARM".to_string();
} else if brand.contains("Qualcomm") {
return "Qualcomm".to_string();
}
brand.to_string()
} else {
"Unknown".to_string()
}
}
fn detect_cpu_model() -> String {
use sysinfo::System;
let mut sys = System::new();
sys.refresh_cpu_all();
sys.cpus()
.first()
.map(|cpu| cpu.brand().to_string())
.unwrap_or_else(|| "Unknown".to_string())
}
const fn detect_gpu_capabilities() -> GpuCapabilities {
let devices = Vec::new();
GpuCapabilities {
available: false,
devices,
primary_device: None,
}
}
fn detect_memory_capabilities() -> MemoryCapabilities {
use sysinfo::System;
let mut sys = System::new_all();
sys.refresh_memory();
MemoryCapabilities {
total_memory: sys.total_memory() as usize,
available_memory: sys.available_memory() as usize,
bandwidth_gbps: detect_memory_bandwidth(),
numa_nodes: detect_numa_nodes(),
hugepage_support: detect_hugepage_support(),
}
}
fn detect_memory_bandwidth() -> Option<f32> {
#[cfg(target_os = "linux")]
{
if let Ok(output) = std::process::Command::new("dmidecode")
.args(["-t", "memory"])
.output()
{
if output.status.success() {
if let Ok(text) = String::from_utf8(output.stdout) {
for line in text.lines() {
if line.contains("Speed:") && line.contains("MT/s") {
if let Some(speed_str) = line.split_whitespace().nth(1) {
if let Ok(speed_mts) = speed_str.parse::<f32>() {
let bandwidth_gbps = (speed_mts * 8.0) / 1000.0;
return Some(bandwidth_gbps);
}
}
}
}
}
}
}
Some(25.0) }
#[cfg(target_os = "macos")]
{
if let Ok(output) = std::process::Command::new("sysctl")
.arg("hw.memsize")
.output()
{
if output.status.success() {
if std::process::Command::new("sysctl")
.arg("machdep.cpu.brand_string")
.output()
.ok()
.and_then(|o| String::from_utf8(o.stdout).ok())
.map(|s| s.contains("Apple"))
.unwrap_or(false)
{
return Some(200.0); }
return Some(30.0); }
}
Some(30.0)
}
#[cfg(target_os = "windows")]
{
Some(25.0)
}
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
{
None
}
}
fn detect_numa_nodes() -> usize {
#[cfg(target_os = "linux")]
{
if let Ok(entries) = std::fs::read_dir("/sys/devices/system/node") {
let node_count = entries
.filter_map(|e| e.ok())
.filter(|e| {
e.file_name().to_string_lossy().starts_with("node") && e.file_name() != "node"
})
.count();
if node_count > 0 {
return node_count;
}
}
if let Ok(output) = std::process::Command::new("numactl")
.arg("--hardware")
.output()
{
if output.status.success() {
if let Ok(text) = String::from_utf8(output.stdout) {
for line in text.lines() {
if line.contains("available:") && line.contains("nodes") {
if let Some(word) = line.split_whitespace().nth(1) {
if let Ok(n) = word.parse::<usize>() {
return n;
}
}
}
}
}
}
}
1 }
#[cfg(target_os = "macos")]
{
1
}
#[cfg(target_os = "windows")]
{
1
}
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
{
1
}
}
fn detect_hugepage_support() -> bool {
#[cfg(target_os = "linux")]
{
std::path::Path::new("/sys/kernel/mm/hugepages").exists()
}
#[cfg(not(target_os = "linux"))]
{
false
}
}
fn detect_platform_type() -> PlatformType {
if env::var("KUBERNETES_SERVICE_HOST").is_ok()
|| env::var("ECS_CONTAINER_METADATA_URI").is_ok()
|| env::var("AWS_EXECUTION_ENV").is_ok()
|| env::var("GOOGLE_CLOUD_PROJECT").is_ok()
|| env::var("AZURE_FUNCTIONS_ENVIRONMENT").is_ok()
{
return PlatformType::Cloud;
}
if cfg!(target_os = "android") || cfg!(target_os = "ios") {
return PlatformType::Mobile;
}
let logical_cores = num_cpus::get();
let physical_cores = num_cpus::get_physical();
use sysinfo::System;
let mut sys = System::new_all();
sys.refresh_memory();
let total_memory_gb = sys.total_memory() / (1024 * 1024 * 1024);
let is_server = logical_cores > 16
|| total_memory_gb > 64
|| detect_numa_nodes() > 1
|| detect_cpu_model().contains("Xeon")
|| detect_cpu_model().contains("EPYC")
|| detect_cpu_model().contains("Threadripper");
if is_server {
PlatformType::Server
} else if cfg!(any(target_arch = "arm", target_arch = "aarch64")) && !cfg!(target_os = "macos")
{
PlatformType::Embedded
} else {
PlatformType::Desktop
}
}
const fn detect_operating_system() -> OperatingSystem {
#[cfg(target_os = "linux")]
{
OperatingSystem::Linux
}
#[cfg(target_os = "windows")]
{
OperatingSystem::Windows
}
#[cfg(target_os = "macos")]
{
OperatingSystem::MacOS
}
#[cfg(target_os = "freebsd")]
{
OperatingSystem::FreeBSD
}
#[cfg(target_os = "android")]
{
OperatingSystem::Android
}
#[cfg(not(any(
target_os = "linux",
target_os = "windows",
target_os = "macos",
target_os = "freebsd",
target_os = "android"
)))]
{
OperatingSystem::Unknown
}
}
const fn detect_architecture() -> Architecture {
#[cfg(target_arch = "x86_64")]
{
Architecture::X86_64
}
#[cfg(target_arch = "aarch64")]
{
Architecture::Aarch64
}
#[cfg(target_arch = "riscv64")]
{
Architecture::Riscv64
}
#[cfg(target_arch = "wasm32")]
{
Architecture::Wasm32
}
#[cfg(not(any(
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "riscv64",
target_arch = "wasm32"
)))]
{
Architecture::Unknown
}
}