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,
}Expand description
A snapshot of where every mapped byte is.
Fields§
§mapped: u64Total bytes mapped from the OS. The anchor.
live: u64Sum of Layout::size() over live allocations — what callers
actually asked for, unrounded.
rounding: u64Sum of (slot size − requested size) over live allocations.
cache: u64Bytes parked on foreign-free lists, waiting to be drained home.
span_free: u64Free slots in spans that were handed out before and returned to the free pool: touched, therefore resident.
returned: u64Bytes whose pages have been handed back to the OS — mapped, not resident. The v2 term: this is what page-granular reclaim produces, and it did not exist while the reclaim unit was the whole span.
Two shapes, both genuinely returned: free slots inside a span
that is still live, and whole spans emptied and retired. The
second used to be filed under hysteresis, so this read 0 while
most of the map had in fact gone back.
virgin: u64Mapped and never touched, therefore not resident: span bytes at or above the bump cursor, and whole spans carved with their segment that no class has ever claimed.
hysteresis: u64Retained rather than released, and therefore still resident: empty spans the per-sweep policy keeps for their class, spans whose discard the platform refused, and large mappings parked in the process-wide retention pool.
Every byte here is one the allocator chose to keep. A byte that
went back to the OS belongs in Self::returned — the two are
opposites, and for the whole v5 arc they were the same number.
segment_overhead: u64Segment headers.
large_count: u64Live allocations served by direct mapping rather than a class.
spans_assigned: u64Spans currently assigned to a size class. Exported because “did we keep claiming fresh spans past reusable ones” is not visible in any byte count — the identity balances either way.
Implementations§
Source§impl Stats
impl Stats
Sourcepub fn accounted(&self) -> u64
pub fn accounted(&self) -> u64
The sum the identity asserts. Kept separate from Self::mapped
so a test can compare the two rather than trusting one.
§Examples
use kevy_alloc::Stats;
// The identity this exists to check: every mapped byte is in
// exactly one bucket, so the sum is comparable to `mapped`
// rather than derived from it.
let s = Stats::default();
assert_eq!(s.accounted(), 0);
assert_eq!(s.mapped, 0);Sourcepub fn predicted_resident(&self) -> u64
pub fn predicted_resident(&self) -> u64
Bytes we expect to be resident: everything mapped except what was never touched or has been handed back to the OS.
An estimate by construction — the kernel decides residency, not us — so it is named as a prediction and compared against real RSS by the gate rather than substituted for it.
hysteresis is NOT subtracted, and used to be. That term is what
the policy is deliberately holding — empty spans kept for their
class, large mappings parked in the retention pool — and holding
is the opposite of handing back. Subtracting it made this
prediction fall by exactly the amount the retention pool grew,
which is the one direction it cannot be right in.