Skip to main content

mnemosyne_arena/segment/
stats.rs

1//! Arena memory telemetry statistics types and helpers.
2
3use super::alloc::SEGMENT_MAPPING_SIZE;
4use super::pool::HasSegmentPool;
5
6/// Snapshot of arena-level segment cache state.
7#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
8pub struct ArenaMemoryStats {
9    pub retained_free_segments: usize,
10    /// Runtime retention cap currently enforced by the segment pool
11    /// (`mnemosyne_core::options::MAX_RETAINED_SEGMENTS`, clamped at set time
12    /// to the compile-time `MAX_RETAINED_SEGMENTS_LIMIT`), not the
13    /// compile-time limit itself.
14    pub max_retained_free_segments: usize,
15    pub retained_free_bytes: usize,
16    pub purged_segments: usize,
17    pub purge_calls: usize,
18    pub purged_bytes: usize,
19    /// Number of segments whose physical backing was released by a
20    /// confirmed `page_reset` while the segment itself remained cached
21    /// in the retained pool.
22    pub reset_segments: usize,
23    /// Number of `reset_segment_pool` invocations.
24    pub reset_calls: usize,
25    /// Number of huge blocks currently retained in the huge-allocation cache
26    /// across all NUMA nodes.
27    pub retained_huge_blocks: usize,
28    /// Total bytes of huge blocks currently retained in the huge-allocation
29    /// cache across all NUMA nodes — typically the dominant share of retained
30    /// RSS.
31    pub retained_huge_bytes: usize,
32}
33
34/// Outcome of attempting to release a segment mapping.
35#[derive(Clone, Copy, Debug, Eq, PartialEq)]
36pub enum SegmentRelease {
37    /// The backend confirmed release of the OS mapping.
38    Released,
39    /// The backend reported release failure; ownership remains with the pool.
40    RetainedAfterFailure,
41}
42
43/// Returns the current arena segment cache counters.
44#[inline]
45pub fn arena_memory_stats<B: HasSegmentPool>() -> ArenaMemoryStats {
46    let pool = B::global_segment_pool();
47    let huge_pool = B::global_huge_pool();
48    let retained = pool.retained_count();
49    ArenaMemoryStats {
50        retained_free_segments: retained,
51        // The runtime option is the enforced cap (`try_push_retained` reads it
52        // per push); the compile-time limit is only its clamp ceiling.
53        max_retained_free_segments: mnemosyne_core::options::MAX_RETAINED_SEGMENTS
54            .load(core::sync::atomic::Ordering::Relaxed),
55        retained_free_bytes: retained * SEGMENT_MAPPING_SIZE,
56        purged_segments: pool.purged_count(),
57        purge_calls: pool.purge_call_count(),
58        purged_bytes: pool.purged_count() * SEGMENT_MAPPING_SIZE,
59        reset_segments: pool.reset_segments_count(),
60        reset_calls: pool.reset_call_count(),
61        retained_huge_blocks: huge_pool.retained_blocks(),
62        retained_huge_bytes: huge_pool.retained_bytes(),
63    }
64}