1use crate::{StorageError, StorageResult};
8use std::{
9 collections::VecDeque,
10 sync::{
11 atomic::{AtomicUsize, Ordering},
12 Arc, Mutex,
13 },
14};
15use tokio::sync::Semaphore;
16
17pub struct PooledBuffer {
22 pub buffer: Vec<u8>,
24 pool: Arc<MemoryPoolInner>,
26 size: usize,
28}
29
30impl PooledBuffer {
31 pub fn clear(&mut self) {
33 self.buffer.clear();
34 }
35
36 pub fn capacity(&self) -> usize {
38 self.buffer.capacity()
39 }
40
41 pub fn write(&mut self, data: &[u8]) -> StorageResult<()> {
43 if self.buffer.len() + data.len() > self.buffer.capacity() {
44 return Err(StorageError::InsufficientSpace {
45 required: data.len() as u64,
46 available: (self.buffer.capacity() - self.buffer.len()) as u64,
47 });
48 }
49 self.buffer.extend_from_slice(data);
50 Ok(())
51 }
52
53 pub fn data(&self) -> &[u8] {
55 &self.buffer
56 }
57
58 pub fn as_mut(&mut self) -> &mut Vec<u8> {
60 &mut self.buffer
61 }
62}
63
64impl Drop for PooledBuffer {
65 fn drop(&mut self) {
66 self.buffer.clear();
68 let buffer = std::mem::take(&mut self.buffer);
69
70 if buffer.capacity() >= self.size {
72 let mut pool = self.pool.buffers.lock().unwrap();
73 if pool.len() < self.pool.max_buffers {
74 pool.push_back(buffer);
75 self.pool.available_count.fetch_add(1, Ordering::Relaxed);
76 }
77 }
78 }
79}
80
81#[derive(Debug)]
83struct MemoryPoolInner {
84 buffers: Mutex<VecDeque<Vec<u8>>>,
86 available_count: AtomicUsize,
88 max_buffers: usize,
90 buffer_size: usize,
92 semaphore: Semaphore,
94}
95
96#[derive(Debug)]
111pub struct MemoryPool {
112 inner: Arc<MemoryPoolInner>,
113 stats: Arc<PoolStats>,
115}
116
117#[derive(Debug, Default)]
119pub struct PoolStats {
120 pub total_gets: AtomicUsize,
122 pub total_returns: AtomicUsize,
124 pub cache_hits: AtomicUsize,
126 pub cache_misses: AtomicUsize,
128 pub active_buffers: AtomicUsize,
130 pub pool_size: AtomicUsize,
132}
133
134impl PoolStats {
135 pub fn hit_rate(&self) -> f64 {
137 let hits = self.cache_hits.load(Ordering::Relaxed) as f64;
138 let total = hits + self.cache_misses.load(Ordering::Relaxed) as f64;
139 if total > 0.0 {
140 hits / total
141 } else {
142 0.0
143 }
144 }
145
146 pub fn utilization(&self) -> f64 {
148 let active = self.active_buffers.load(Ordering::Relaxed) as f64;
149 let total = self.pool_size.load(Ordering::Relaxed) as f64;
150 if total > 0.0 {
151 active / total
152 } else {
153 0.0
154 }
155 }
156}
157
158impl MemoryPool {
159 pub fn new(pool_size_bytes: usize, buffer_size: usize) -> StorageResult<Self> {
168 let max_buffers = pool_size_bytes / buffer_size;
169
170 if max_buffers == 0 {
171 return Err(StorageError::configuration(
172 "Pool size too small for requested buffer size"
173 ));
174 }
175
176 let mut buffers = VecDeque::with_capacity(max_buffers);
177
178 for _ in 0..max_buffers {
180 let mut buffer = Vec::with_capacity(buffer_size);
181 buffer.reserve_exact(buffer_size);
182 buffers.push_back(buffer);
183 }
184
185 let stats = Arc::new(PoolStats::default());
186 stats.pool_size.store(max_buffers, Ordering::Relaxed);
187
188 let inner = Arc::new(MemoryPoolInner {
189 buffers: Mutex::new(buffers),
190 available_count: AtomicUsize::new(max_buffers),
191 max_buffers,
192 buffer_size,
193 semaphore: Semaphore::new(max_buffers),
194 });
195
196 tracing::info!(
197 "MemoryPool initialized: {} buffers, {} bytes each, {} MB total",
198 max_buffers,
199 buffer_size,
200 pool_size_bytes / (1024 * 1024)
201 );
202
203 Ok(Self { inner, stats })
204 }
205
206 pub async fn get_buffer(&self) -> StorageResult<PooledBuffer> {
211 let _permit = self.inner.semaphore.acquire().await
213 .map_err(|_| StorageError::internal("Failed to acquire buffer permit"))?;
214
215 self.stats.total_gets.fetch_add(1, Ordering::Relaxed);
216
217 if let Some(buffer) = self.try_get_from_pool() {
219 self.stats.cache_hits.fetch_add(1, Ordering::Relaxed);
220 self.stats.active_buffers.fetch_add(1, Ordering::Relaxed);
221
222 return Ok(PooledBuffer {
223 buffer,
224 pool: Arc::clone(&self.inner),
225 size: self.inner.buffer_size,
226 });
227 }
228
229 self.stats.cache_misses.fetch_add(1, Ordering::Relaxed);
231 self.stats.active_buffers.fetch_add(1, Ordering::Relaxed);
232
233 let mut buffer = Vec::with_capacity(self.inner.buffer_size);
234 buffer.reserve_exact(self.inner.buffer_size);
235
236 Ok(PooledBuffer {
237 buffer,
238 pool: Arc::clone(&self.inner),
239 size: self.inner.buffer_size,
240 })
241 }
242
243 fn try_get_from_pool(&self) -> Option<Vec<u8>> {
245 let mut buffers = self.inner.buffers.lock().ok()?;
246 if let Some(buffer) = buffers.pop_front() {
247 self.inner.available_count.fetch_sub(1, Ordering::Relaxed);
248 Some(buffer)
249 } else {
250 None
251 }
252 }
253
254 pub fn stats(&self) -> PoolStats {
256 PoolStats {
257 total_gets: AtomicUsize::new(self.stats.total_gets.load(Ordering::Relaxed)),
258 total_returns: AtomicUsize::new(self.stats.total_returns.load(Ordering::Relaxed)),
259 cache_hits: AtomicUsize::new(self.stats.cache_hits.load(Ordering::Relaxed)),
260 cache_misses: AtomicUsize::new(self.stats.cache_misses.load(Ordering::Relaxed)),
261 active_buffers: AtomicUsize::new(self.stats.active_buffers.load(Ordering::Relaxed)),
262 pool_size: AtomicUsize::new(self.stats.pool_size.load(Ordering::Relaxed)),
263 }
264 }
265
266 pub fn health_check(&self) -> bool {
268 let available = self.inner.available_count.load(Ordering::Relaxed);
269 let active = self.stats.active_buffers.load(Ordering::Relaxed);
270 let total = available + active;
271
272 total <= self.inner.max_buffers
274 }
275
276 pub async fn warmup(&self) -> StorageResult<()> {
278 tracing::info!("Warming up memory pool...");
279
280 let warmup_count = self.inner.max_buffers / 2;
281 let mut buffers = Vec::new();
282
283 for _ in 0..warmup_count {
285 if let Ok(buffer) = self.get_buffer().await {
286 buffers.push(buffer);
287 }
288 }
289
290 drop(buffers);
292
293 tracing::info!("Memory pool warmup completed");
294 Ok(())
295 }
296}
297
298pub struct ParallelBufferProcessor {
302 pool: Arc<MemoryPool>,
303 worker_count: usize,
304}
305
306impl ParallelBufferProcessor {
307 pub fn new(pool: Arc<MemoryPool>, worker_count: Option<usize>) -> Self {
309 let worker_count = worker_count.unwrap_or_else(|| {
310 std::thread::available_parallelism()
311 .map(|n| n.get() * 2)
312 .unwrap_or(8)
313 });
314
315 Self { pool, worker_count }
316 }
317
318 pub async fn process_batch<T, F, Fut>(
320 &self,
321 items: Vec<T>,
322 processor: F,
323 ) -> StorageResult<Vec<StorageResult<()>>>
324 where
325 T: Send + 'static + Clone,
326 F: Fn(T, PooledBuffer) -> Fut + Send + Sync + 'static,
327 Fut: std::future::Future<Output = StorageResult<()>> + Send,
328 {
329 let processor = Arc::new(processor);
330 let chunk_size = (items.len() + self.worker_count - 1) / self.worker_count;
331
332 let mut handles = Vec::new();
333
334 for chunk in items.chunks(chunk_size) {
335 let chunk = chunk.to_vec();
336 let pool = Arc::clone(&self.pool);
337 let processor = Arc::clone(&processor);
338
339 let handle = tokio::spawn(async move {
340 let mut results = Vec::new();
341
342 for item in chunk {
343 match pool.get_buffer().await {
344 Ok(buffer) => {
345 let result = processor(item, buffer).await;
346 results.push(result);
347 }
348 Err(e) => {
349 results.push(Err(e));
350 }
351 }
352 }
353
354 results
355 });
356
357 handles.push(handle);
358 }
359
360 let mut all_results = Vec::new();
361 for handle in handles {
362 match handle.await {
363 Ok(results) => all_results.extend(results),
364 Err(e) => return Err(StorageError::internal(format!("Worker task failed: {}", e))),
365 }
366 }
367
368 Ok(all_results)
369 }
370}
371
372#[cfg(test)]
373mod tests {
374 use super::*;
375 use tokio;
376
377 #[tokio::test]
378 async fn test_memory_pool_basic_operations() {
379 let pool = MemoryPool::new(1024 * 1024, 1024).unwrap(); let mut buffer = pool.get_buffer().await.unwrap();
383 assert_eq!(buffer.capacity(), 1024);
384
385 let test_data = b"Hello, Memory Pool!";
387 buffer.write(test_data).unwrap();
388 assert_eq!(buffer.data(), test_data);
389
390 drop(buffer);
392
393 let stats = pool.stats();
395 assert_eq!(stats.total_gets.load(Ordering::Relaxed), 1);
396 }
397
398 #[tokio::test]
399 async fn test_concurrent_buffer_access() {
400 let pool = Arc::new(MemoryPool::new(10 * 1024, 1024).unwrap()); let mut handles = Vec::new();
403
404 for i in 0..5 {
406 let pool_clone = Arc::clone(&pool);
407 let handle = tokio::spawn(async move {
408 let mut buffer = pool_clone.get_buffer().await.unwrap();
409 buffer.write(format!("Data {}", i).as_bytes()).unwrap();
410 tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
412 buffer
413 });
414 handles.push(handle);
415 }
416
417 for handle in handles {
419 let _buffer = handle.await.unwrap();
420 }
421
422 assert!(pool.health_check());
424 }
425}