use std::fmt::Write as _;
use serde::{Deserialize, Serialize};
use crate::config::ByteSize;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum AdmissionPolicy {
#[default]
Caps,
Measured,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case", tag = "kind")]
pub enum Basis {
Job {
runs: u64,
},
Profile {
runs: u64,
},
ProfileMax {
runs: u64,
},
Overran {
until: u64,
},
Cap,
Unpredictable {
until: u64,
},
Unmeasured,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct Admission {
pub policy: AdmissionPolicy,
pub reserved: u64,
pub basis: Basis,
pub free: Option<u64>,
pub slice: Option<u64>,
}
impl Admission {
pub fn line(&self) -> String {
let size = |bytes: u64| ByteSize(bytes).to_string();
let reserved = size(self.reserved);
let why = match self.basis {
Basis::Job { runs } => {
format!("reserved {reserved}, the p95 peak of {runs} runs of its job + the margin")
}
Basis::Profile { runs } => format!(
"reserved {reserved}, from {runs} runs of its profile: its job had too few of its own"
),
Basis::ProfileMax { runs } => format!(
"reserved {reserved}, the largest peak of {runs} runs of its profile + the margin: its job had no \
runs of its own"
),
Basis::Overran { .. } => format!(
"reserved {reserved}, its job's largest peak + the margin: a run of it went past what it reserved \
lately"
),
Basis::Cap if self.policy == AdmissionPolicy::Caps => {
format!("reserved its {reserved} cap")
}
Basis::Cap => format!("reserved its {reserved} cap: too few runs to predict from"),
Basis::Unpredictable { .. } => format!(
"reserved its {reserved} cap: a run of its job peaked at its cap or was killed for memory lately"
),
Basis::Unmeasured => {
format!("reserved its {reserved} cap: no recent sample of the slice's memory")
}
};
let policy = match self.policy {
AdmissionPolicy::Caps => "caps",
AdmissionPolicy::Measured => "measured peaks",
};
let mut line = format!("admitted by {policy}: {why}");
if let Some(free) = self.free {
let _ = write!(line, "; {} of the budget was free", size(free));
}
if let Some(slice) = self.slice {
let _ = write!(line, ", the slice at {}", size(slice));
}
line
}
}