pub fn detect_system_ram_mb() -> Option<u64> {
#[cfg(target_os = "linux")]
{
detect_linux_ram()
}
#[cfg(target_os = "macos")]
{
detect_macos_ram()
}
#[cfg(target_os = "windows")]
{
detect_windows_ram()
}
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
{
None
}
}
#[cfg(target_os = "linux")]
fn detect_linux_ram() -> Option<u64> {
use std::fs::read_to_string;
let meminfo = read_to_string("/proc/meminfo").ok()?;
for line in meminfo.lines() {
if line.starts_with("MemTotal:") {
let parts: Vec<&str> = line.split_whitespace().collect();
if parts.len() >= 2 {
if let Ok(kb) = parts[1].parse::<u64>() {
return Some(kb / 1024); }
}
break;
}
}
None
}
#[cfg(target_os = "macos")]
fn detect_macos_ram() -> Option<u64> {
use std::process::Command;
let output = Command::new("sysctl")
.arg("-n")
.arg("hw.memsize")
.output()
.ok()?;
if output.status.success() {
let bytes_str = String::from_utf8(output.stdout).ok()?;
if let Ok(bytes) = bytes_str.trim().parse::<u64>() {
return Some(bytes / 1024 / 1024); }
}
None
}
#[cfg(target_os = "windows")]
fn detect_windows_ram() -> Option<u64> {
use std::process::Command;
let output = Command::new("wmic")
.args(["OS", "get", "TotalVisibleMemorySize"])
.output()
.ok()?;
if output.status.success() {
let kb_str = String::from_utf8(output.stdout).ok()?;
if let Ok(kb) = kb_str.trim().parse::<u64>() {
return Some(kb / 1024); }
}
None
}
pub fn calculate_auto_budget(system_ram_mb: u64) -> u64 {
let budget = system_ram_mb / 4; budget.clamp(32, 4096) }
pub fn estimate_key_capacity(budget_mb: u64) -> u64 {
(budget_mb * 1024 * 1024).div_ceil(84)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_calculate_auto_budget() {
assert_eq!(calculate_auto_budget(128), 32); assert_eq!(calculate_auto_budget(256), 64); assert_eq!(calculate_auto_budget(1024), 256); assert_eq!(calculate_auto_budget(4096), 1024); assert_eq!(calculate_auto_budget(16384), 4096); assert_eq!(calculate_auto_budget(32768), 4096); }
#[test]
fn test_estimate_key_capacity() {
let capacity_16 = estimate_key_capacity(16);
assert!(
capacity_16 > 190_000 && capacity_16 < 200_000,
"16MB should be ~190K keys, got {}",
capacity_16
);
let capacity_64 = estimate_key_capacity(64);
assert!(
capacity_64 > 790_000 && capacity_64 < 800_000,
"64MB should be ~798K keys, got {}",
capacity_64
);
let capacity_256 = estimate_key_capacity(256);
assert!(
capacity_256 > 3_100_000 && capacity_256 < 3_200_000,
"256MB should be ~3.19M keys, got {}",
capacity_256
);
}
}