use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::OnceLock;
pub const DEFAULT_PROCESS_BUDGET_BYTES: u64 = 2 * 1024 * 1024 * 1024;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Pressure {
Low,
High,
Critical,
}
impl Pressure {
pub fn allows_columnar(&self) -> bool {
matches!(self, Pressure::Low)
}
}
struct Watermark {
budget_bytes: AtomicU64,
reserved_bytes: AtomicU64,
}
static WATERMARK: OnceLock<Watermark> = OnceLock::new();
fn watermark() -> &'static Watermark {
WATERMARK.get_or_init(|| Watermark {
budget_bytes: AtomicU64::new(DEFAULT_PROCESS_BUDGET_BYTES),
reserved_bytes: AtomicU64::new(0),
})
}
pub fn set_process_budget(bytes: u64) {
watermark().budget_bytes.store(bytes, Ordering::Relaxed);
}
pub fn reserved() -> u64 {
watermark().reserved_bytes.load(Ordering::Relaxed)
}
pub fn try_reserve(bytes: u64) -> bool {
let w = watermark();
let mut prev = w.reserved_bytes.load(Ordering::Relaxed);
loop {
let total = match prev.checked_add(bytes) {
Some(t) => t,
None => return false,
};
if total > w.budget_bytes.load(Ordering::Relaxed) {
return false;
}
match w.reserved_bytes.compare_exchange_weak(
prev,
total,
Ordering::AcqRel,
Ordering::Relaxed,
) {
Ok(_) => return true,
Err(current) => prev = current,
}
}
}
pub fn release(bytes: u64) {
let w = watermark();
let prev = w.reserved_bytes.fetch_sub(bytes, Ordering::AcqRel);
debug_assert!(prev >= bytes, "watermark release underflow");
}
pub fn pressure() -> Pressure {
let w = watermark();
let budget = w.budget_bytes.load(Ordering::Relaxed).max(1);
let used = w.reserved_bytes.load(Ordering::Relaxed);
const HIGH_PCT: u64 = 70;
const CRITICAL_PCT: u64 = 90;
if used.saturating_mul(100) >= budget.saturating_mul(CRITICAL_PCT) {
Pressure::Critical
} else if used.saturating_mul(100) >= budget.saturating_mul(HIGH_PCT) {
Pressure::High
} else {
Pressure::Low
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn reservation_accounts_and_releases() {
set_process_budget(1024);
assert!(try_reserve(512));
assert_eq!(reserved(), 512);
assert!(pressure() == Pressure::Low || pressure() == Pressure::High);
assert!(
!try_reserve(600),
"over-budget reservation must be rejected"
);
release(512);
assert_eq!(reserved(), 0);
set_process_budget(DEFAULT_PROCESS_BUDGET_BYTES);
}
#[test]
fn pressure_levels_follow_watermarks() {
set_process_budget(1000);
release(reserved());
try_reserve(500); assert_eq!(pressure(), Pressure::Low);
try_reserve(250); assert_eq!(pressure(), Pressure::High);
try_reserve(200); assert_eq!(pressure(), Pressure::Critical);
release(950);
assert_eq!(pressure(), Pressure::Low);
set_process_budget(DEFAULT_PROCESS_BUDGET_BYTES);
}
#[test]
fn columnar_allowed_only_under_low_pressure() {
set_process_budget(1000);
release(reserved());
try_reserve(990);
assert_eq!(pressure(), Pressure::Critical);
assert!(!pressure().allows_columnar());
release(990);
assert!(pressure().allows_columnar());
set_process_budget(DEFAULT_PROCESS_BUDGET_BYTES);
}
}