use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum MemoryPressure {
#[default]
Unknown,
Normal,
Warn,
Critical,
}
impl MemoryPressure {
pub fn derive(available_mb: Option<u32>, total_mb: Option<u32>) -> Self {
let (Some(avail), Some(total)) = (available_mb, total_mb) else {
return Self::Unknown;
};
if total == 0 {
return Self::Unknown;
}
let ratio = avail as f64 / total as f64;
if ratio < 0.05 {
Self::Critical
} else if ratio < 0.15 {
Self::Warn
} else {
Self::Normal
}
}
pub fn worse_of(self, other: Self) -> Self {
fn rank(p: MemoryPressure) -> u8 {
match p {
MemoryPressure::Unknown => 0,
MemoryPressure::Normal => 1,
MemoryPressure::Warn => 2,
MemoryPressure::Critical => 3,
}
}
if rank(other) > rank(self) {
other
} else {
self
}
}
pub fn as_str(&self) -> &'static str {
match self {
MemoryPressure::Unknown => "unknown",
MemoryPressure::Normal => "normal",
MemoryPressure::Warn => "warn",
MemoryPressure::Critical => "critical",
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn derive_unknown_when_either_none() {
assert_eq!(MemoryPressure::derive(None, None), MemoryPressure::Unknown);
assert_eq!(
MemoryPressure::derive(Some(1024), None),
MemoryPressure::Unknown
);
assert_eq!(
MemoryPressure::derive(None, Some(8192)),
MemoryPressure::Unknown
);
}
#[test]
fn derive_unknown_when_total_zero() {
assert_eq!(
MemoryPressure::derive(Some(0), Some(0)),
MemoryPressure::Unknown
);
}
#[test]
fn derive_critical_under_5pct() {
assert_eq!(
MemoryPressure::derive(Some(200), Some(8192)),
MemoryPressure::Critical
);
assert_eq!(
MemoryPressure::derive(Some(410), Some(8192)),
MemoryPressure::Warn
);
}
#[test]
fn derive_warn_5_to_15pct() {
assert_eq!(
MemoryPressure::derive(Some(800), Some(8000)),
MemoryPressure::Warn
);
assert_eq!(
MemoryPressure::derive(Some(1200), Some(8000)),
MemoryPressure::Normal
);
}
#[test]
fn derive_normal_above_15pct() {
assert_eq!(
MemoryPressure::derive(Some(4096), Some(8192)),
MemoryPressure::Normal
);
}
#[test]
fn worse_of_picks_higher_severity() {
assert_eq!(
MemoryPressure::Normal.worse_of(MemoryPressure::Warn),
MemoryPressure::Warn
);
assert_eq!(
MemoryPressure::Warn.worse_of(MemoryPressure::Critical),
MemoryPressure::Critical
);
assert_eq!(
MemoryPressure::Critical.worse_of(MemoryPressure::Normal),
MemoryPressure::Critical
);
}
#[test]
fn worse_of_prefers_real_reading_over_unknown() {
assert_eq!(
MemoryPressure::Unknown.worse_of(MemoryPressure::Normal),
MemoryPressure::Normal
);
assert_eq!(
MemoryPressure::Normal.worse_of(MemoryPressure::Unknown),
MemoryPressure::Normal
);
}
}