use std::sync::OnceLock;
use sysinfo::{Pid, ProcessRefreshKind, RefreshKind, System};
static MEMORY_LIMIT_MB: OnceLock<Option<u64>> = OnceLock::new();
pub fn memory_limit_mb() -> Option<u64> {
*MEMORY_LIMIT_MB.get_or_init(|| {
std::env::var("TRUSTY_MEMORY_LIMIT_MB")
.ok()
.and_then(|v| v.parse::<u64>().ok())
.filter(|&n| n > 0)
})
}
pub fn current_rss_mb() -> Option<u64> {
let pid = Pid::from_u32(std::process::id());
let mut sys = System::new_with_specifics(
RefreshKind::nothing().with_processes(ProcessRefreshKind::everything()),
);
sys.refresh_processes_specifics(
sysinfo::ProcessesToUpdate::Some(&[pid]),
true,
ProcessRefreshKind::nothing().with_memory(),
);
sys.process(pid).map(|p| p.memory() / (1024 * 1024))
}
pub fn over_memory_limit() -> bool {
match (memory_limit_mb(), current_rss_mb()) {
(Some(limit), Some(rss)) => rss >= limit,
_ => false,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_memory_limit_env_parse() {
let _ = memory_limit_mb();
}
#[test]
fn test_current_rss_mb_nonzero() {
if let Some(mb) = current_rss_mb() {
assert!(mb > 0, "current process RSS should be > 0 MB, got {mb}");
}
}
#[test]
fn test_over_memory_limit_false_when_unset() {
if memory_limit_mb().is_none() {
assert!(!over_memory_limit());
}
}
}