Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion server_manager/benches/service_benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,21 @@ fn benchmark_port_matrix_generation(c: &mut Criterion) {
});
}

fn benchmark_hardware_detection(c: &mut Criterion) {
c.bench_function("hardware_detection", |b| {
b.iter(|| {
let hw = HardwareInfo::detect();
criterion::black_box(hw);
})
});
}

criterion_group!(
benches,
benchmark_catalog_retrieval,
benchmark_compose_generation,
benchmark_validation_throughput,
benchmark_port_matrix_generation
benchmark_port_matrix_generation,
benchmark_hardware_detection
);
criterion_main!(benches);
37 changes: 27 additions & 10 deletions server_manager/src/core/hardware.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use log::{info, warn};
use nix::unistd::User;
use std::path::Path;
use std::sync::OnceLock;
use sysinfo::{DiskExt, System, SystemExt};
use which::which;

static HARDWARE_CACHE: OnceLock<HardwareInfo> = OnceLock::new();

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum HardwareProfile {
Low, // < 4GB RAM, <= 2 cores
Expand All @@ -26,6 +29,10 @@ pub struct HardwareInfo {

impl HardwareInfo {
pub fn detect() -> Self {
HARDWARE_CACHE.get_or_init(Self::detect_uncached).clone()
}

pub fn detect_uncached() -> Self {
let (user_id, group_id) = Self::detect_user();
let mut sys = System::new();
sys.refresh_memory();
Expand All @@ -41,16 +48,17 @@ impl HardwareInfo {

let cpu_cores = sys.cpus().len();

let mut disk_gb = 0;
for disk in sys.disks() {
// Filter out virtual filesystems to prevent double counting (e.g., overlayfs)
let fs_type = std::str::from_utf8(disk.file_system()).unwrap_or("unknown");
match fs_type {
"overlay" | "tmpfs" | "devtmpfs" | "squashfs" | "sysfs" | "proc" => continue,
_ => {}
}
disk_gb += disk.total_space() / 1024 / 1024 / 1024;
}
let disk_gb = sys
.disks()
.iter()
.filter(|disk| {
!matches!(
disk.file_system(),
b"overlay" | b"tmpfs" | b"devtmpfs" | b"squashfs" | b"sysfs" | b"proc"
)
})
.map(|disk| disk.total_space() / 1024 / 1024 / 1024)
.sum();

let profile = Self::evaluate_profile(ram_gb, cpu_cores, swap_gb);

Expand Down Expand Up @@ -158,4 +166,13 @@ mod tests {
HardwareProfile::Standard
); // 6GB RAM + Swap -> Standard
}

#[test]
fn test_hardware_info_cached_and_uncached_detection() {
let hw_uncached = HardwareInfo::detect_uncached();
let hw_cached = HardwareInfo::detect();
assert_eq!(hw_uncached.cpu_cores, hw_cached.cpu_cores);
assert_eq!(hw_uncached.ram_gb, hw_cached.ram_gb);
assert_eq!(hw_uncached.profile, hw_cached.profile);
}
}
Loading