1use parking_lot::Mutex;
7use scirs2_core::Complex;
8use std::sync::atomic::{AtomicU64, Ordering};
9use std::sync::Arc;
10
11#[derive(Debug, Clone, Default)]
13pub struct PoolStatistics {
14 pub hits: u64,
16 pub misses: u64,
18 pub bytes_allocated: u64,
20 pub bytes_reused: u64,
22}
23
24impl PoolStatistics {
25 pub fn hit_rate(&self) -> f64 {
27 let total = self.hits + self.misses;
28 if total == 0 {
29 0.0
30 } else {
31 self.hits as f64 / total as f64
32 }
33 }
34
35 pub fn memory_efficiency(&self) -> f64 {
37 let total = self.bytes_allocated + self.bytes_reused;
38 if total == 0 {
39 0.0
40 } else {
41 self.bytes_reused as f64 / total as f64
42 }
43 }
44}
45
46pub struct AudioBufferPool {
48 buffers: Arc<Mutex<Vec<Vec<f32>>>>,
50 max_pooled: usize,
52 default_capacity: usize,
54 hits: Arc<AtomicU64>,
56 misses: Arc<AtomicU64>,
57 bytes_allocated: Arc<AtomicU64>,
58 bytes_reused: Arc<AtomicU64>,
59}
60
61impl AudioBufferPool {
62 pub fn new(max_pooled: usize, default_capacity: usize) -> Self {
68 Self {
69 buffers: Arc::new(Mutex::new(Vec::with_capacity(max_pooled))),
70 max_pooled,
71 default_capacity,
72 hits: Arc::new(AtomicU64::new(0)),
73 misses: Arc::new(AtomicU64::new(0)),
74 bytes_allocated: Arc::new(AtomicU64::new(0)),
75 bytes_reused: Arc::new(AtomicU64::new(0)),
76 }
77 }
78
79 pub fn acquire(&self, min_capacity: usize) -> PooledBuffer {
87 let mut buffers = self.buffers.lock();
88
89 if let Some(pos) = buffers
91 .iter()
92 .position(|buf| buf.capacity() >= min_capacity)
93 {
94 let mut buffer = buffers.swap_remove(pos);
95 let capacity = buffer.capacity();
96 buffer.clear();
97
98 self.hits.fetch_add(1, Ordering::Relaxed);
100 self.bytes_reused.fetch_add(
101 (capacity * std::mem::size_of::<f32>()) as u64,
102 Ordering::Relaxed,
103 );
104
105 return PooledBuffer {
106 buffer: Some(buffer),
107 pool: Arc::clone(&self.buffers),
108 max_pooled: self.max_pooled,
109 };
110 }
111
112 drop(buffers);
114 let capacity = min_capacity.max(self.default_capacity);
115
116 self.misses.fetch_add(1, Ordering::Relaxed);
118 self.bytes_allocated.fetch_add(
119 (capacity * std::mem::size_of::<f32>()) as u64,
120 Ordering::Relaxed,
121 );
122
123 PooledBuffer {
124 buffer: Some(Vec::with_capacity(capacity)),
125 pool: Arc::clone(&self.buffers),
126 max_pooled: self.max_pooled,
127 }
128 }
129
130 pub fn pool_size(&self) -> usize {
132 self.buffers.lock().len()
133 }
134
135 pub fn clear(&self) {
137 self.buffers.lock().clear();
138 }
139
140 pub fn statistics(&self) -> PoolStatistics {
142 PoolStatistics {
143 hits: self.hits.load(Ordering::Relaxed),
144 misses: self.misses.load(Ordering::Relaxed),
145 bytes_allocated: self.bytes_allocated.load(Ordering::Relaxed),
146 bytes_reused: self.bytes_reused.load(Ordering::Relaxed),
147 }
148 }
149
150 pub fn reset_statistics(&self) {
152 self.hits.store(0, Ordering::Relaxed);
153 self.misses.store(0, Ordering::Relaxed);
154 self.bytes_allocated.store(0, Ordering::Relaxed);
155 self.bytes_reused.store(0, Ordering::Relaxed);
156 }
157}
158
159impl Default for AudioBufferPool {
160 fn default() -> Self {
161 Self::new(16, 4096)
162 }
163}
164
165pub struct PooledBuffer {
167 buffer: Option<Vec<f32>>,
168 pool: Arc<Mutex<Vec<Vec<f32>>>>,
169 max_pooled: usize,
170}
171
172impl PooledBuffer {
173 fn get_mut(&mut self) -> &mut Vec<f32> {
175 self.buffer.as_mut().expect("Buffer already consumed")
176 }
177
178 fn get_ref(&self) -> &Vec<f32> {
180 self.buffer.as_ref().expect("Buffer already consumed")
181 }
182
183 pub fn into_inner(mut self) -> Vec<f32> {
185 self.buffer.take().expect("Buffer already consumed")
186 }
187}
188
189impl Drop for PooledBuffer {
190 fn drop(&mut self) {
191 if let Some(mut buffer) = self.buffer.take() {
192 let mut pool = self.pool.lock();
193 if pool.len() < self.max_pooled {
194 buffer.clear();
195 pool.push(buffer);
196 }
197 }
198 }
199}
200
201impl std::ops::Deref for PooledBuffer {
202 type Target = Vec<f32>;
203
204 fn deref(&self) -> &Self::Target {
205 self.get_ref()
206 }
207}
208
209impl std::ops::DerefMut for PooledBuffer {
210 fn deref_mut(&mut self) -> &mut Self::Target {
211 self.get_mut()
212 }
213}
214
215pub struct ComplexBufferPool {
217 buffers: Arc<Mutex<Vec<Vec<Complex<f32>>>>>,
219 max_pooled: usize,
221 default_capacity: usize,
223 hits: Arc<AtomicU64>,
225 misses: Arc<AtomicU64>,
226 bytes_allocated: Arc<AtomicU64>,
227 bytes_reused: Arc<AtomicU64>,
228}
229
230impl ComplexBufferPool {
231 pub fn new(max_pooled: usize, default_capacity: usize) -> Self {
233 Self {
234 buffers: Arc::new(Mutex::new(Vec::with_capacity(max_pooled))),
235 max_pooled,
236 default_capacity,
237 hits: Arc::new(AtomicU64::new(0)),
238 misses: Arc::new(AtomicU64::new(0)),
239 bytes_allocated: Arc::new(AtomicU64::new(0)),
240 bytes_reused: Arc::new(AtomicU64::new(0)),
241 }
242 }
243
244 pub fn acquire(&self, min_capacity: usize) -> PooledComplexBuffer {
246 let mut buffers = self.buffers.lock();
247
248 if let Some(pos) = buffers
250 .iter()
251 .position(|buf| buf.capacity() >= min_capacity)
252 {
253 let mut buffer = buffers.swap_remove(pos);
254 let capacity = buffer.capacity();
255 buffer.clear();
256
257 self.hits.fetch_add(1, Ordering::Relaxed);
259 self.bytes_reused.fetch_add(
260 (capacity * std::mem::size_of::<Complex<f32>>()) as u64,
261 Ordering::Relaxed,
262 );
263
264 return PooledComplexBuffer {
265 buffer: Some(buffer),
266 pool: Arc::clone(&self.buffers),
267 max_pooled: self.max_pooled,
268 };
269 }
270
271 drop(buffers);
273 let capacity = min_capacity.max(self.default_capacity);
274
275 self.misses.fetch_add(1, Ordering::Relaxed);
277 self.bytes_allocated.fetch_add(
278 (capacity * std::mem::size_of::<Complex<f32>>()) as u64,
279 Ordering::Relaxed,
280 );
281
282 PooledComplexBuffer {
283 buffer: Some(Vec::with_capacity(capacity)),
284 pool: Arc::clone(&self.buffers),
285 max_pooled: self.max_pooled,
286 }
287 }
288
289 pub fn pool_size(&self) -> usize {
291 self.buffers.lock().len()
292 }
293
294 pub fn clear(&self) {
296 self.buffers.lock().clear();
297 }
298
299 pub fn statistics(&self) -> PoolStatistics {
301 PoolStatistics {
302 hits: self.hits.load(Ordering::Relaxed),
303 misses: self.misses.load(Ordering::Relaxed),
304 bytes_allocated: self.bytes_allocated.load(Ordering::Relaxed),
305 bytes_reused: self.bytes_reused.load(Ordering::Relaxed),
306 }
307 }
308
309 pub fn reset_statistics(&self) {
311 self.hits.store(0, Ordering::Relaxed);
312 self.misses.store(0, Ordering::Relaxed);
313 self.bytes_allocated.store(0, Ordering::Relaxed);
314 self.bytes_reused.store(0, Ordering::Relaxed);
315 }
316}
317
318impl Default for ComplexBufferPool {
319 fn default() -> Self {
320 Self::new(16, 4096)
321 }
322}
323
324pub struct PooledComplexBuffer {
326 buffer: Option<Vec<Complex<f32>>>,
327 pool: Arc<Mutex<Vec<Vec<Complex<f32>>>>>,
328 max_pooled: usize,
329}
330
331impl PooledComplexBuffer {
332 fn get_mut(&mut self) -> &mut Vec<Complex<f32>> {
333 self.buffer.as_mut().expect("Buffer already consumed")
334 }
335
336 fn get_ref(&self) -> &Vec<Complex<f32>> {
337 self.buffer.as_ref().expect("Buffer already consumed")
338 }
339
340 pub fn into_inner(mut self) -> Vec<Complex<f32>> {
342 self.buffer.take().expect("Buffer already consumed")
343 }
344}
345
346impl Drop for PooledComplexBuffer {
347 fn drop(&mut self) {
348 if let Some(mut buffer) = self.buffer.take() {
349 let mut pool = self.pool.lock();
350 if pool.len() < self.max_pooled {
351 buffer.clear();
352 pool.push(buffer);
353 }
354 }
355 }
356}
357
358impl std::ops::Deref for PooledComplexBuffer {
359 type Target = Vec<Complex<f32>>;
360
361 fn deref(&self) -> &Self::Target {
362 self.get_ref()
363 }
364}
365
366impl std::ops::DerefMut for PooledComplexBuffer {
367 fn deref_mut(&mut self) -> &mut Self::Target {
368 self.get_mut()
369 }
370}
371
372thread_local! {
374 static BUFFER_POOL: AudioBufferPool = AudioBufferPool::default();
375 static COMPLEX_BUFFER_POOL: ComplexBufferPool = ComplexBufferPool::default();
376}
377
378pub fn get_pooled_buffer(min_capacity: usize) -> PooledBuffer {
395 BUFFER_POOL.with(|pool| pool.acquire(min_capacity))
396}
397
398pub fn get_pooled_complex_buffer(min_capacity: usize) -> PooledComplexBuffer {
416 COMPLEX_BUFFER_POOL.with(|pool| pool.acquire(min_capacity))
417}
418
419pub fn pool_size() -> usize {
421 BUFFER_POOL.with(|pool| pool.pool_size())
422}
423
424pub fn complex_pool_size() -> usize {
426 COMPLEX_BUFFER_POOL.with(|pool| pool.pool_size())
427}
428
429pub fn clear_pool() {
431 BUFFER_POOL.with(|pool| pool.clear());
432}
433
434pub fn clear_complex_pool() {
436 COMPLEX_BUFFER_POOL.with(|pool| pool.clear());
437}
438
439pub fn pool_statistics() -> PoolStatistics {
441 BUFFER_POOL.with(|pool| pool.statistics())
442}
443
444pub fn complex_pool_statistics() -> PoolStatistics {
446 COMPLEX_BUFFER_POOL.with(|pool| pool.statistics())
447}
448
449pub fn reset_pool_statistics() {
451 BUFFER_POOL.with(|pool| pool.reset_statistics());
452}
453
454pub fn reset_complex_pool_statistics() {
456 COMPLEX_BUFFER_POOL.with(|pool| pool.reset_statistics());
457}
458
459#[cfg(test)]
460mod tests {
461 use super::*;
462
463 #[test]
464 fn test_buffer_pool_acquire_release() {
465 let pool = AudioBufferPool::new(4, 1024);
466
467 let buffer = pool.acquire(512);
469 assert!(buffer.capacity() >= 512);
470 assert_eq!(pool.pool_size(), 0);
471
472 drop(buffer);
474 assert_eq!(pool.pool_size(), 1);
475
476 let buffer = pool.acquire(512);
478 assert_eq!(pool.pool_size(), 0);
479 }
480
481 #[test]
482 fn test_buffer_pool_capacity_growth() {
483 let pool = AudioBufferPool::new(4, 1024);
484
485 let buffer = pool.acquire(2048);
487 assert!(buffer.capacity() >= 2048);
488 }
489
490 #[test]
491 fn test_buffer_pool_max_pooled() {
492 let pool = AudioBufferPool::new(2, 1024);
493
494 let b1 = pool.acquire(512);
496 let b2 = pool.acquire(512);
497 let b3 = pool.acquire(512);
498
499 drop(b1);
500 drop(b2);
501 assert_eq!(pool.pool_size(), 2);
502
503 drop(b3);
505 assert_eq!(pool.pool_size(), 2);
506 }
507
508 #[test]
509 fn test_pooled_buffer_deref() {
510 let pool = AudioBufferPool::new(4, 1024);
511 let mut buffer = pool.acquire(512);
512
513 buffer.extend_from_slice(&[1.0, 2.0, 3.0]);
515 assert_eq!(buffer.len(), 3);
516 assert_eq!(buffer[0], 1.0);
517 }
518
519 #[test]
520 fn test_pooled_buffer_into_inner() {
521 let pool = AudioBufferPool::new(4, 1024);
522 let mut buffer = pool.acquire(512);
523 buffer.extend_from_slice(&[1.0, 2.0, 3.0]);
524
525 let vec = buffer.into_inner();
526 assert_eq!(vec.len(), 3);
527 assert_eq!(vec[0], 1.0);
528
529 assert_eq!(pool.pool_size(), 0);
531 }
532
533 #[test]
534 fn test_thread_local_pool() {
535 clear_pool();
537 assert_eq!(pool_size(), 0);
538
539 let buffer = get_pooled_buffer(1024);
541 drop(buffer);
542 assert_eq!(pool_size(), 1);
543
544 let buffer = get_pooled_buffer(512);
546 assert_eq!(pool_size(), 0);
547 drop(buffer);
548 assert_eq!(pool_size(), 1);
549 }
550
551 #[test]
552 fn test_clear_pool() {
553 clear_pool();
554 let b1 = get_pooled_buffer(512);
555 let b2 = get_pooled_buffer(512);
556 drop(b1);
557 drop(b2);
558 assert_eq!(pool_size(), 2);
559
560 clear_pool();
561 assert_eq!(pool_size(), 0);
562 }
563
564 #[test]
565 fn test_pool_statistics() {
566 let pool = AudioBufferPool::new(4, 1024);
567 pool.reset_statistics();
568
569 let b1 = pool.acquire(512);
571 drop(b1);
572
573 let stats = pool.statistics();
574 assert_eq!(stats.misses, 1);
575 assert_eq!(stats.hits, 0);
576 assert!(stats.bytes_allocated > 0);
577
578 let b2 = pool.acquire(512);
580 drop(b2);
581
582 let stats = pool.statistics();
583 assert_eq!(stats.misses, 1);
584 assert_eq!(stats.hits, 1);
585 assert!(stats.bytes_reused > 0);
586
587 assert!((stats.hit_rate() - 0.5).abs() < 0.01);
589 }
590
591 #[test]
592 fn test_pool_statistics_memory_efficiency() {
593 let pool = AudioBufferPool::new(4, 1024);
594 pool.reset_statistics();
595
596 for _ in 0..10 {
598 let b = pool.acquire(512);
599 drop(b);
600 }
601
602 let stats = pool.statistics();
603 assert_eq!(stats.misses, 1);
605 assert_eq!(stats.hits, 9);
606
607 assert!(stats.memory_efficiency() > 0.85);
609 }
610
611 #[test]
612 fn test_complex_buffer_pool() {
613 let pool = ComplexBufferPool::new(4, 1024);
614
615 let mut buffer = pool.acquire(512);
617 assert!(buffer.capacity() >= 512);
618
619 buffer.push(Complex::new(1.0, 2.0));
621 buffer.push(Complex::new(3.0, 4.0));
622 assert_eq!(buffer.len(), 2);
623
624 drop(buffer);
626 assert_eq!(pool.pool_size(), 1);
627
628 let buffer = pool.acquire(512);
630 assert_eq!(buffer.len(), 0); assert_eq!(pool.pool_size(), 0);
632 }
633
634 #[test]
635 fn test_complex_buffer_statistics() {
636 let pool = ComplexBufferPool::new(4, 1024);
637 pool.reset_statistics();
638
639 let b1 = pool.acquire(512);
641 drop(b1);
642
643 let stats = pool.statistics();
644 assert_eq!(stats.misses, 1);
645 assert_eq!(stats.hits, 0);
646
647 let expected_bytes = 1024 * std::mem::size_of::<Complex<f32>>();
649 assert_eq!(stats.bytes_allocated as usize, expected_bytes);
650
651 let b2 = pool.acquire(512);
653 drop(b2);
654
655 let stats = pool.statistics();
656 assert_eq!(stats.hits, 1);
657 assert!(stats.bytes_reused > 0);
658 }
659
660 #[test]
661 fn test_thread_local_complex_pool() {
662 clear_complex_pool();
663 reset_complex_pool_statistics();
664
665 let mut buffer = get_pooled_complex_buffer(1024);
667 buffer.push(Complex::new(1.0, 0.0));
668 drop(buffer);
669
670 assert_eq!(complex_pool_size(), 1);
671
672 let stats = complex_pool_statistics();
674 assert_eq!(stats.misses, 1);
675 assert_eq!(stats.hits, 0);
676
677 let buffer = get_pooled_complex_buffer(512);
679 drop(buffer);
680
681 let stats = complex_pool_statistics();
682 assert_eq!(stats.hits, 1);
683 assert!(stats.hit_rate() > 0.4);
684 }
685
686 #[test]
687 fn test_pooled_complex_buffer_deref() {
688 let pool = ComplexBufferPool::new(4, 1024);
689 let mut buffer = pool.acquire(512);
690
691 buffer.extend_from_slice(&[Complex::new(1.0, 2.0), Complex::new(3.0, 4.0)]);
693
694 assert_eq!(buffer.len(), 2);
695 assert_eq!(buffer[0], Complex::new(1.0, 2.0));
696 assert_eq!(buffer[1], Complex::new(3.0, 4.0));
697 }
698
699 #[test]
700 fn test_pooled_complex_buffer_into_inner() {
701 let pool = ComplexBufferPool::new(4, 1024);
702 let mut buffer = pool.acquire(512);
703
704 buffer.push(Complex::new(1.0, 2.0));
705 let vec = buffer.into_inner();
706
707 assert_eq!(vec.len(), 1);
708 assert_eq!(vec[0], Complex::new(1.0, 2.0));
709
710 assert_eq!(pool.pool_size(), 0);
712 }
713
714 #[test]
715 fn test_statistics_reset() {
716 let pool = AudioBufferPool::new(4, 1024);
717
718 for _ in 0..5 {
720 let b = pool.acquire(512);
721 drop(b);
722 }
723
724 let stats = pool.statistics();
725 assert!(stats.hits > 0 || stats.misses > 0);
726
727 pool.reset_statistics();
729 let stats = pool.statistics();
730 assert_eq!(stats.hits, 0);
731 assert_eq!(stats.misses, 0);
732 assert_eq!(stats.bytes_allocated, 0);
733 assert_eq!(stats.bytes_reused, 0);
734 }
735
736 #[test]
737 fn test_thread_local_statistics() {
738 reset_pool_statistics();
739 reset_complex_pool_statistics();
740
741 let b1 = get_pooled_buffer(1024);
743 drop(b1);
744
745 let stats = pool_statistics();
746 assert_eq!(stats.misses, 1);
747
748 let b2 = get_pooled_complex_buffer(1024);
750 drop(b2);
751
752 let complex_stats = complex_pool_statistics();
753 assert_eq!(complex_stats.misses, 1);
754
755 assert_eq!(stats.misses, 1);
757 assert_eq!(complex_stats.misses, 1);
758 }
759}