Skip to main content

pedant_graph/cache/
stats.rs

1//! What one cache did, counted once per examined or dropped entry.
2//!
3//! Statistics describe cache work alone. Nothing here enters graph identity,
4//! record order, serialization, or a query answer: a counter is read by a host
5//! deciding whether its retention budget is worth the memory, and by the proofs
6//! that hold this crate to reusing only what it claims to reuse.
7//!
8//! The reading is a copied value. The live counts it is taken from belong to
9//! [`super::state`], so a host reads a number that cannot move under it.
10
11/// One category's three cumulative counts, as a copied reading.
12#[derive(Clone, Copy, Debug, PartialEq, Eq)]
13pub(crate) struct CategoryCounts {
14    hits: u64,
15    misses: u64,
16    evictions: u64,
17}
18
19impl CategoryCounts {
20    /// One category's three counts, read together.
21    pub(crate) fn new(hits: u64, misses: u64, evictions: u64) -> Self {
22        Self {
23            hits,
24            misses,
25            evictions,
26        }
27    }
28}
29
30/// A copied reading of one cache's cumulative activity.
31///
32/// Counters saturate rather than wrap, so a long-lived host reads a ceiling
33/// instead of a count that silently restarted.
34#[derive(Clone, Copy, Debug, PartialEq, Eq)]
35pub struct GraphCacheStats {
36    source_projections: CategoryCounts,
37    exact_graphs: CategoryCounts,
38    selected_indexes: CategoryCounts,
39    derived_products: CategoryCounts,
40}
41
42impl GraphCacheStats {
43    /// One reading, taken across all four categories at once.
44    pub(crate) fn new(
45        source_projections: CategoryCounts,
46        exact_graphs: CategoryCounts,
47        selected_indexes: CategoryCounts,
48        derived_products: CategoryCounts,
49    ) -> Self {
50        Self {
51            source_projections,
52            exact_graphs,
53            selected_indexes,
54            derived_products,
55        }
56    }
57
58    /// Source-unit projections reused from retained state.
59    pub fn source_projection_hits(self) -> u64 {
60        self.source_projections.hits
61    }
62
63    /// Source-unit projections that had to be rebuilt.
64    pub fn source_projection_misses(self) -> u64 {
65        self.source_projections.misses
66    }
67
68    /// Source-unit projections dropped to stay within their ceiling.
69    pub fn source_projection_evictions(self) -> u64 {
70        self.source_projections.evictions
71    }
72
73    /// Exact graphs answered from retained state.
74    pub fn exact_graph_hits(self) -> u64 {
75        self.exact_graphs.hits
76    }
77
78    /// Exact graphs that had to be built.
79    pub fn exact_graph_misses(self) -> u64 {
80        self.exact_graphs.misses
81    }
82
83    /// Exact graphs dropped to stay within their ceiling.
84    pub fn exact_graph_evictions(self) -> u64 {
85        self.exact_graphs.evictions
86    }
87
88    /// Edge-selection index sets answered from retained state.
89    pub fn selected_index_hits(self) -> u64 {
90        self.selected_indexes.hits
91    }
92
93    /// Edge-selection index sets that had to be built.
94    pub fn selected_index_misses(self) -> u64 {
95        self.selected_indexes.misses
96    }
97
98    /// Edge-selection index sets dropped to stay within their ceiling.
99    pub fn selected_index_evictions(self) -> u64 {
100        self.selected_indexes.evictions
101    }
102
103    /// Derived products answered from retained state.
104    pub fn derived_product_hits(self) -> u64 {
105        self.derived_products.hits
106    }
107
108    /// Derived products that had to be computed.
109    pub fn derived_product_misses(self) -> u64 {
110        self.derived_products.misses
111    }
112
113    /// Derived products dropped to stay within their ceiling.
114    pub fn derived_product_evictions(self) -> u64 {
115        self.derived_products.evictions
116    }
117}