use std::sync::{
OnceLock,
atomic::{AtomicU64, AtomicUsize, Ordering},
};
const CHECK_INTERVAL_MS: u64 = 1000;
static INSTANCE: OnceLock<MemoryPressure> = OnceLock::new();
pub fn init(threshold: usize) {
INSTANCE.get_or_init(|| MemoryPressure::new(threshold));
}
pub fn is_exceeded() -> bool {
INSTANCE.get().is_some_and(MemoryPressure::is_exceeded)
}
pub struct MemoryPressure {
cached_rss: AtomicUsize,
last_check_ms: AtomicU64,
threshold: usize,
}
impl MemoryPressure {
pub fn new(threshold: usize) -> Self {
Self {
cached_rss: AtomicUsize::new(0),
last_check_ms: AtomicU64::new(0),
threshold,
}
}
pub fn is_exceeded(&self) -> bool {
self.maybe_refresh();
self.cached_rss.load(Ordering::Relaxed) > self.threshold
}
fn maybe_refresh(&self) {
let now = epoch_ms();
let last = self.last_check_ms.load(Ordering::Relaxed);
if now.saturating_sub(last) < CHECK_INTERVAL_MS {
return;
}
if self
.last_check_ms
.compare_exchange(last, now, Ordering::Relaxed, Ordering::Relaxed)
.is_err()
{
return;
}
if let Some(rss) = sample_rss() {
self.cached_rss.store(rss, Ordering::Relaxed);
}
}
}
fn epoch_ms() -> u64 {
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.ok()
.and_then(|d| u64::try_from(d.as_millis()).ok())
.unwrap_or(0)
}
#[cfg(target_os = "linux")]
fn sample_rss() -> Option<usize> {
let status = std::fs::read_to_string("/proc/self/status").ok()?;
for line in status.lines() {
if let Some(rest) = line.strip_prefix("VmRSS:") {
let kb: usize = rest.trim().strip_suffix("kB")?.trim().parse().ok()?;
return kb.checked_mul(1024);
}
}
None
}
#[cfg(not(target_os = "linux"))]
fn sample_rss() -> Option<usize> {
None
}
#[cfg(test)]
#[expect(clippy::allow_attributes, reason = "blanket test suppressions")]
#[allow(clippy::unwrap_used, clippy::expect_used, clippy::indexing_slicing, reason = "tests")]
mod tests {
use super::*;
#[test]
fn new_monitor_starts_at_zero_rss() {
let mp = MemoryPressure::new(1024);
assert_eq!(
mp.cached_rss.load(Ordering::Relaxed),
0,
"initial cached RSS should be zero"
);
}
#[test]
fn very_large_threshold_never_exceeded() {
let mp = MemoryPressure::new(usize::MAX);
assert!(!mp.is_exceeded(), "usize::MAX threshold should never be exceeded");
}
#[cfg(target_os = "linux")]
#[test]
fn sample_rss_returns_positive_value() {
let rss = sample_rss();
assert!(rss.is_some_and(|v| v > 0), "RSS should be a positive value on Linux");
}
#[cfg(target_os = "linux")]
#[test]
fn tiny_threshold_is_exceeded() {
let mp = MemoryPressure::new(1);
assert!(mp.is_exceeded(), "1-byte threshold should always be exceeded");
}
#[test]
fn is_exceeded_without_init_returns_false() {
assert!(
!is_exceeded(),
"global is_exceeded should return false when uninitialized"
);
}
#[test]
fn epoch_ms_returns_nonzero() {
assert!(epoch_ms() > 0, "epoch_ms should return a positive value");
}
}