#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct Stats {
pub mapped: u64,
pub live: u64,
pub rounding: u64,
pub cache: u64,
pub span_free: u64,
pub returned: u64,
pub virgin: u64,
pub hysteresis: u64,
pub segment_overhead: u64,
pub large_count: u64,
pub spans_assigned: u64,
}
impl Stats {
#[must_use]
pub fn accounted(&self) -> u64 {
self.live
+ self.rounding
+ self.cache
+ self.span_free
+ self.returned
+ self.virgin
+ self.hysteresis
+ self.segment_overhead
}
#[must_use]
pub fn balanced(&self) -> bool {
self.mapped == self.accounted()
}
#[must_use]
pub fn predicted_resident(&self) -> u64 {
self.mapped - self.virgin - self.hysteresis - self.returned
}
pub fn merge(&mut self, other: &Stats) {
self.mapped += other.mapped;
self.live += other.live;
self.rounding += other.rounding;
self.cache += other.cache;
self.span_free += other.span_free;
self.returned += other.returned;
self.virgin += other.virgin;
self.hysteresis += other.hysteresis;
self.segment_overhead += other.segment_overhead;
self.large_count += other.large_count;
self.spans_assigned += other.spans_assigned;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn an_empty_heap_balances() {
assert!(Stats::default().balanced());
}
#[test]
fn merge_is_additive_in_every_term() {
let a = Stats { mapped: 10, live: 4, virgin: 6, ..Stats::default() };
let mut sum = a;
sum.merge(&a);
assert_eq!(sum.mapped, 20);
assert_eq!(sum.live, 8);
assert_eq!(sum.virgin, 12);
assert!(sum.balanced());
}
#[test]
fn an_imbalance_is_visible() {
let bad = Stats { mapped: 100, live: 1, ..Stats::default() };
assert!(!bad.balanced());
assert_eq!(bad.accounted(), 1);
}
}