use super::*;
thread_local! {
static ACTIVE_PHASE: RefCell<Option<std::borrow::Cow<'static, str>>> =
const { RefCell::new(None) };
}
pub fn current_phase_label() -> Option<std::borrow::Cow<'static, str>> {
ACTIVE_PHASE.with(|p| p.borrow().clone())
}
#[must_use = "PhaseGuard restores the prior phase on Drop — bind it to a local"]
pub struct PhaseGuard {
previous: Option<std::borrow::Cow<'static, str>>,
}
impl PhaseGuard {
pub fn install(label: impl Into<std::borrow::Cow<'static, str>>) -> Self {
let previous = ACTIVE_PHASE.with(|p| p.replace(Some(label.into())));
Self { previous }
}
pub fn install_step(zero_indexed: u16) -> Self {
Self::install(format!("Step[{}]", zero_indexed))
}
pub fn install_baseline() -> Self {
Self::install(std::borrow::Cow::Borrowed("BASELINE"))
}
}
impl Drop for PhaseGuard {
fn drop(&mut self) {
ACTIVE_PHASE.with(|p| {
*p.borrow_mut() = self.previous.take();
});
}
}
#[derive(Debug, Clone, Default)]
pub struct NumaMapsEntry {
pub addr: u64,
pub node_pages: BTreeMap<usize, u64>,
}
pub fn parse_numa_maps(content: &str) -> Vec<NumaMapsEntry> {
let mut entries = Vec::new();
for line in content.lines() {
let line = line.trim();
if line.is_empty() {
continue;
}
let mut parts = line.split_whitespace();
let addr = match parts.next().and_then(|s| u64::from_str_radix(s, 16).ok()) {
Some(a) => a,
None => continue,
};
let _ = parts.next();
let mut entry = NumaMapsEntry {
addr,
..Default::default()
};
for token in parts {
if let Some(rest) = token.strip_prefix('N')
&& let Some((node_str, count_str)) = rest.split_once('=')
&& let (Ok(node), Ok(count)) = (node_str.parse::<usize>(), count_str.parse::<u64>())
{
*entry.node_pages.entry(node).or_insert(0) += count;
}
}
if !entry.node_pages.is_empty() {
entries.push(entry);
}
}
entries
}
pub fn page_locality(entries: &[NumaMapsEntry], expected_nodes: &BTreeSet<usize>) -> f64 {
let mut total: u64 = 0;
let mut local: u64 = 0;
for entry in entries {
for (&node, &count) in &entry.node_pages {
total += count;
if expected_nodes.contains(&node) {
local += count;
}
}
}
if total > 0 {
local as f64 / total as f64
} else {
0.0
}
}
pub fn parse_vmstat_numa_pages_migrated(content: &str) -> Option<u64> {
for line in content.lines() {
let line = line.trim();
if let Some(rest) = line.strip_prefix("numa_pages_migrated") {
let rest = rest.trim();
if let Ok(v) = rest.parse::<u64>() {
return Some(v);
}
}
}
None
}
pub(crate) fn gap_threshold_ms() -> u64 {
if cfg!(debug_assertions) { 3000 } else { 2000 }
}
pub(crate) fn spread_threshold_pct() -> f64 {
if cfg!(debug_assertions) { 35.0 } else { 15.0 }
}