oxiphysics_gpu/compute/
buffer_pool.rs1use std::collections::HashMap;
10
11pub struct BufferPool {
16 pub pools: HashMap<usize, Vec<Vec<f64>>>,
18 pub cap_per_bucket: usize,
20}
21
22impl BufferPool {
23 pub fn new() -> Self {
25 Self {
26 pools: HashMap::new(),
27 cap_per_bucket: 64,
28 }
29 }
30
31 pub fn alloc(&mut self, len: usize) -> Vec<f64> {
37 let bucket = len.next_power_of_two();
38 self.pools
39 .entry(bucket)
40 .or_default()
41 .pop()
42 .unwrap_or_else(|| vec![0.0; bucket])
43 }
44
45 pub fn free(&mut self, len: usize, buf: Vec<f64>) {
50 let bucket = len.next_power_of_two();
51 let pool = self.pools.entry(bucket).or_default();
52 if pool.len() < self.cap_per_bucket {
53 pool.push(buf);
54 }
55 }
57
58 pub fn total_free(&self) -> usize {
60 self.pools.values().map(|v| v.len()).sum()
61 }
62
63 pub fn clear(&mut self) {
65 self.pools.clear();
66 }
67}
68
69impl Default for BufferPool {
70 fn default() -> Self {
71 Self::new()
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 #[test]
80 fn test_pool_alloc_returns_correctly_sized_vec() {
81 let mut pool = BufferPool::new();
82 let buf = pool.alloc(10);
83 assert!(buf.len() >= 10);
85 assert_eq!(buf.capacity(), 16);
86 }
87
88 #[test]
89 fn test_pool_alloc_free_reuses_buffer() {
90 let mut pool = BufferPool::new();
91 let buf = pool.alloc(8);
92 let ptr = buf.as_ptr();
93 pool.free(8, buf);
94 let buf2 = pool.alloc(8);
95 assert_eq!(buf2.as_ptr(), ptr);
97 }
98
99 #[test]
100 fn test_pool_bucket_cap_does_not_grow_unbounded() {
101 let mut pool = BufferPool::new();
102 pool.cap_per_bucket = 4;
103 for _ in 0..8 {
105 let buf = vec![0.0f64; 8];
106 pool.free(8, buf);
107 }
108 assert_eq!(pool.total_free(), 4);
109 }
110
111 #[test]
112 fn test_pool_clear_releases_all() {
113 let mut pool = BufferPool::new();
114 pool.free(4, vec![0.0; 4]);
115 pool.free(8, vec![0.0; 8]);
116 assert_eq!(pool.total_free(), 2);
117 pool.clear();
118 assert_eq!(pool.total_free(), 0);
119 }
120
121 #[test]
122 fn test_pool_alloc_zero_len_returns_power_of_two() {
123 let mut pool = BufferPool::new();
124 let buf = pool.alloc(0);
126 assert!(!buf.is_empty());
127 }
128}