safer_ring/pool/
stats.rs

1//! Pool statistics and monitoring.
2
3/// Statistics about buffer pool usage.
4///
5/// Provides insights into pool performance and utilization patterns.
6/// All statistics are captured at a specific point in time and may
7/// become stale as the pool state changes.
8///
9/// # Examples
10///
11/// ```rust
12/// use safer_ring::pool::BufferPool;
13///
14/// let pool = BufferPool::new(10, 4096);
15/// let stats = pool.stats();
16///
17/// println!("Pool utilization: {:.1}%", stats.utilization_percent());
18/// println!("Success rate: {:.1}%", stats.success_rate_percent());
19/// ```
20#[derive(Debug, Clone, Copy, PartialEq)]
21pub struct PoolStats {
22    /// Total capacity of the pool
23    pub capacity: usize,
24    /// Number of buffers currently available
25    pub available: usize,
26    /// Number of buffers currently in use
27    pub in_use: usize,
28    /// Size of each buffer in bytes
29    pub buffer_size: usize,
30    /// Total successful allocations since pool creation
31    pub total_allocations: u64,
32    /// Total failed allocation attempts since pool creation
33    pub failed_allocations: u64,
34    /// Current utilization as a ratio (0.0 to 1.0)
35    pub utilization: f64,
36    /// Total number of buffers in the pool (same as capacity)
37    pub total_buffers: usize,
38    /// Number of buffers currently available (same as available)
39    pub available_buffers: usize,
40    /// Number of buffers currently in use (same as in_use)
41    pub in_use_buffers: usize,
42}
43
44impl PoolStats {
45    /// Get utilization as a percentage (0.0 to 100.0).
46    ///
47    /// # Examples
48    ///
49    /// ```rust
50    /// # use safer_ring::pool::PoolStats;
51    /// let stats = PoolStats {
52    ///     capacity: 10,
53    ///     available: 3,
54    ///     in_use: 7,
55    ///     buffer_size: 4096,
56    ///     total_allocations: 100,
57    ///     failed_allocations: 5,
58    ///     utilization: 0.7,
59    ///     total_buffers: 10,
60    ///     available_buffers: 3,
61    ///     in_use_buffers: 7,
62    /// };
63    /// assert_eq!(stats.utilization_percent(), 70.0);
64    /// ```
65    pub fn utilization_percent(&self) -> f64 {
66        self.utilization * 100.0
67    }
68
69    /// Get the success rate of allocations as a percentage (0.0 to 100.0).
70    ///
71    /// Returns 100.0 if no allocation attempts have been made.
72    ///
73    /// # Examples
74    ///
75    /// ```rust
76    /// # use safer_ring::pool::PoolStats;
77    /// let stats = PoolStats {
78    ///     capacity: 10,
79    ///     available: 5,
80    ///     in_use: 5,
81    ///     buffer_size: 4096,
82    ///     total_allocations: 95,
83    ///     failed_allocations: 5,
84    ///     utilization: 0.5,
85    ///     total_buffers: 10,
86    ///     available_buffers: 5,
87    ///     in_use_buffers: 5,
88    /// };
89    /// assert_eq!(stats.success_rate_percent(), 95.0);
90    /// ```
91    pub fn success_rate_percent(&self) -> f64 {
92        let total_attempts = self.total_allocations + self.failed_allocations;
93        if total_attempts == 0 {
94            100.0 // No attempts means perfect success rate
95        } else {
96            (self.total_allocations as f64 / total_attempts as f64) * 100.0
97        }
98    }
99
100    /// Get the total memory allocated by the pool in bytes.
101    ///
102    /// # Examples
103    ///
104    /// ```rust
105    /// # use safer_ring::pool::PoolStats;
106    /// let stats = PoolStats {
107    ///     capacity: 10,
108    ///     buffer_size: 4096,
109    ///     // ... other fields
110    ///     # available: 5, in_use: 5, total_allocations: 100,
111    ///     # failed_allocations: 0, utilization: 0.5,
112    ///     # total_buffers: 10, available_buffers: 5, in_use_buffers: 5,
113    /// };
114    /// assert_eq!(stats.total_memory_bytes(), 40960); // 10 * 4096
115    /// ```
116    pub fn total_memory_bytes(&self) -> usize {
117        self.capacity * self.buffer_size
118    }
119
120    /// Get the memory currently in use in bytes.
121    pub fn memory_in_use_bytes(&self) -> usize {
122        self.in_use * self.buffer_size
123    }
124
125    /// Check if the pool is under high pressure (utilization > 80%).
126    ///
127    /// This can be used to trigger alerts or scaling decisions.
128    ///
129    /// # Examples
130    ///
131    /// ```rust
132    /// # use safer_ring::pool::PoolStats;
133    /// let high_pressure = PoolStats {
134    ///     utilization: 0.85, // 85% utilization
135    ///     # capacity: 10, available: 2, in_use: 8, buffer_size: 4096,
136    ///     # total_allocations: 100, failed_allocations: 0,
137    ///     # total_buffers: 10, available_buffers: 2, in_use_buffers: 8,
138    /// };
139    /// assert!(high_pressure.is_under_pressure());
140    ///
141    /// let normal_pressure = PoolStats {
142    ///     utilization: 0.60, // 60% utilization
143    ///     # capacity: 10, available: 4, in_use: 6, buffer_size: 4096,
144    ///     # total_allocations: 100, failed_allocations: 0,
145    ///     # total_buffers: 10, available_buffers: 4, in_use_buffers: 6,
146    /// };
147    /// assert!(!normal_pressure.is_under_pressure());
148    /// ```
149    pub fn is_under_pressure(&self) -> bool {
150        self.utilization > 0.8
151    }
152
153    /// Check if the pool has experienced allocation failures.
154    pub fn has_allocation_failures(&self) -> bool {
155        self.failed_allocations > 0
156    }
157}