oxilean_kernel/hash_cons/
stats.rs1#[derive(Debug, Clone, Copy, PartialEq)]
7pub struct HashConsStats {
8 pub hits: u64,
10 pub misses: u64,
12 pub total: u64,
14 pub unique_nodes: usize,
16}
17
18impl HashConsStats {
19 pub fn hit_rate(&self) -> f64 {
23 if self.total == 0 {
24 return 0.0;
25 }
26 self.hits as f64 / self.total as f64
27 }
28
29 pub fn dedup_ratio(&self) -> f64 {
33 if self.total == 0 {
34 return 0.0;
35 }
36 self.misses as f64 / self.total as f64
37 }
38
39 pub fn has_dedup(&self) -> bool {
41 self.hits > 0
42 }
43}
44
45impl std::fmt::Display for HashConsStats {
46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 write!(
48 f,
49 "HashConsStats {{ hits: {}, misses: {}, total: {}, unique_nodes: {}, hit_rate: {:.2}% }}",
50 self.hits,
51 self.misses,
52 self.total,
53 self.unique_nodes,
54 self.hit_rate() * 100.0,
55 )
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn test_stats_hit_rate_zero_total() {
65 let s = HashConsStats {
66 hits: 0,
67 misses: 0,
68 total: 0,
69 unique_nodes: 0,
70 };
71 assert_eq!(s.hit_rate(), 0.0);
72 }
73
74 #[test]
75 fn test_stats_hit_rate_all_hits() {
76 let s = HashConsStats {
77 hits: 10,
78 misses: 0,
79 total: 10,
80 unique_nodes: 5,
81 };
82 assert!((s.hit_rate() - 1.0).abs() < f64::EPSILON);
83 }
84
85 #[test]
86 fn test_stats_dedup_ratio() {
87 let s = HashConsStats {
88 hits: 7,
89 misses: 3,
90 total: 10,
91 unique_nodes: 3,
92 };
93 assert!((s.dedup_ratio() - 0.3).abs() < 1e-10);
94 }
95
96 #[test]
97 fn test_stats_has_dedup_true() {
98 let s = HashConsStats {
99 hits: 1,
100 misses: 9,
101 total: 10,
102 unique_nodes: 9,
103 };
104 assert!(s.has_dedup());
105 }
106
107 #[test]
108 fn test_stats_has_dedup_false_when_no_hits() {
109 let s = HashConsStats {
110 hits: 0,
111 misses: 5,
112 total: 5,
113 unique_nodes: 5,
114 };
115 assert!(!s.has_dedup());
116 }
117
118 #[test]
119 fn test_stats_display_does_not_panic() {
120 let s = HashConsStats {
121 hits: 3,
122 misses: 2,
123 total: 5,
124 unique_nodes: 2,
125 };
126 let text = format!("{}", s);
127 assert!(text.contains("hits: 3"));
128 assert!(text.contains("misses: 2"));
129 }
130}