1mod collector;
4mod reporter;
5
6pub use collector::StatisticsCollector;
7pub use reporter::StatisticsReporter;
8
9use core::fmt;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
32pub struct PoolStatistics {
33 pub total_allocations: usize,
35
36 pub total_deallocations: usize,
38
39 pub current_usage: usize,
41
42 pub peak_usage: usize,
44
45 pub capacity: usize,
47
48 pub growth_count: usize,
50
51 pub allocation_failures: usize,
53}
54
55impl PoolStatistics {
56 pub fn new(capacity: usize) -> Self {
58 Self {
59 total_allocations: 0,
60 total_deallocations: 0,
61 current_usage: 0,
62 peak_usage: 0,
63 capacity,
64 growth_count: 0,
65 allocation_failures: 0,
66 }
67 }
68
69 #[inline]
71 pub fn utilization_rate(&self) -> f64 {
72 if self.capacity == 0 {
73 0.0
74 } else {
75 (self.current_usage as f64 / self.capacity as f64) * 100.0
76 }
77 }
78
79 #[inline]
81 pub fn peak_utilization_rate(&self) -> f64 {
82 if self.capacity == 0 {
83 0.0
84 } else {
85 (self.peak_usage as f64 / self.capacity as f64) * 100.0
86 }
87 }
88
89 #[inline]
91 pub fn hit_rate(&self) -> f64 {
92 let total_attempts = self.total_allocations + self.allocation_failures;
93 if total_attempts == 0 {
94 1.0
95 } else {
96 self.total_allocations as f64 / total_attempts as f64
97 }
98 }
99
100 #[inline]
102 pub fn available(&self) -> usize {
103 self.capacity.saturating_sub(self.current_usage)
104 }
105}
106
107impl fmt::Display for PoolStatistics {
108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109 writeln!(f, "Pool Statistics:")?;
110 writeln!(f, " Capacity: {}", self.capacity)?;
111 writeln!(
112 f,
113 " Current Usage: {} ({:.1}%)",
114 self.current_usage,
115 self.utilization_rate()
116 )?;
117 writeln!(
118 f,
119 " Peak Usage: {} ({:.1}%)",
120 self.peak_usage,
121 self.peak_utilization_rate()
122 )?;
123 writeln!(f, " Total Allocations: {}", self.total_allocations)?;
124 writeln!(f, " Total Deallocations: {}", self.total_deallocations)?;
125 writeln!(f, " Allocation Failures: {}", self.allocation_failures)?;
126 writeln!(f, " Hit Rate: {:.2}%", self.hit_rate() * 100.0)?;
127 writeln!(f, " Growth Count: {}", self.growth_count)?;
128 Ok(())
129 }
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135
136 #[test]
137 fn statistics_utilization() {
138 let stats = PoolStatistics {
139 capacity: 100,
140 current_usage: 50,
141 peak_usage: 75,
142 ..PoolStatistics::new(100)
143 };
144
145 assert_eq!(stats.utilization_rate(), 50.0);
146 assert_eq!(stats.peak_utilization_rate(), 75.0);
147 }
148
149 #[test]
150 fn statistics_hit_rate() {
151 let stats = PoolStatistics {
152 total_allocations: 90,
153 allocation_failures: 10,
154 ..PoolStatistics::new(100)
155 };
156
157 assert_eq!(stats.hit_rate(), 0.9);
158 }
159
160 #[test]
161 fn statistics_available() {
162 let stats = PoolStatistics {
163 capacity: 100,
164 current_usage: 30,
165 ..PoolStatistics::new(100)
166 };
167
168 assert_eq!(stats.available(), 70);
169 }
170}