Skip to main content

reifydb_core/value/column/pool/
mod.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (c) 2025 ReifyDB
3
4//! Container pooling infrastructure for efficient memory management during
5//! expression evaluation.
6//!
7//! This module provides pooling for all container types to avoid frequent
8//! allocations and deallocations during column operations. Each container
9//! type has its own pool that manages reusable instances.
10
11pub mod allocator;
12pub mod capacity;
13pub mod config;
14pub mod guard;
15pub mod lazy;
16pub mod scoped;
17pub mod stats;
18#[cfg(test)]
19pub mod testing;
20pub mod thread_local;
21
22use std::{collections::HashMap, ops::Deref, rc::Rc};
23
24use reifydb_type::value::{
25	container::{
26		blob::BlobContainer, bool::BoolContainer, number::NumberContainer, row::RowNumberContainer,
27		temporal::TemporalContainer, utf8::Utf8Container, uuid::UuidContainer,
28	},
29	date::Date,
30	datetime::DateTime,
31	duration::Duration,
32	time::Time,
33	uuid::{Uuid4, Uuid7},
34};
35
36use crate::value::column::pool::{
37	allocator::{PoolAllocator, StdPoolAllocator},
38	stats::PoolStats,
39};
40
41#[derive(Clone)]
42pub struct Pools(Rc<PoolsInner>);
43
44impl Deref for Pools {
45	type Target = PoolsInner;
46
47	fn deref(&self) -> &Self::Target {
48		&self.0
49	}
50}
51
52pub struct PoolsInner {
53	bool_pool: StdPoolAllocator<BoolContainer>,
54	string_pool: StdPoolAllocator<Utf8Container>,
55	blob_pool: StdPoolAllocator<BlobContainer>,
56	row_number_pool: StdPoolAllocator<RowNumberContainer>,
57	// Numeric pools for all types
58	i8_pool: StdPoolAllocator<NumberContainer<i8>>,
59	i16_pool: StdPoolAllocator<NumberContainer<i16>>,
60	i32_pool: StdPoolAllocator<NumberContainer<i32>>,
61	i64_pool: StdPoolAllocator<NumberContainer<i64>>,
62	i128_pool: StdPoolAllocator<NumberContainer<i128>>,
63	u8_pool: StdPoolAllocator<NumberContainer<u8>>,
64	u16_pool: StdPoolAllocator<NumberContainer<u16>>,
65	u32_pool: StdPoolAllocator<NumberContainer<u32>>,
66	u64_pool: StdPoolAllocator<NumberContainer<u64>>,
67	u128_pool: StdPoolAllocator<NumberContainer<u128>>,
68	f32_pool: StdPoolAllocator<NumberContainer<f32>>,
69	f64_pool: StdPoolAllocator<NumberContainer<f64>>,
70
71	// Temporal pools
72	date_pool: StdPoolAllocator<TemporalContainer<Date>>,
73	datetime_pool: StdPoolAllocator<TemporalContainer<DateTime>>,
74	time_pool: StdPoolAllocator<TemporalContainer<Time>>,
75	duration_pool: StdPoolAllocator<TemporalContainer<Duration>>,
76
77	// UUID pools
78	uuid4_pool: StdPoolAllocator<UuidContainer<Uuid4>>,
79	uuid7_pool: StdPoolAllocator<UuidContainer<Uuid7>>,
80}
81
82impl Default for Pools {
83	fn default() -> Self {
84		Self::new(16) // Default max pool size of 16 containers per bucket
85	}
86}
87
88impl Pools {
89	pub fn new(max_pool_size: usize) -> Self {
90		Self(Rc::new(PoolsInner {
91			bool_pool: StdPoolAllocator::new(max_pool_size),
92			string_pool: StdPoolAllocator::new(max_pool_size),
93			blob_pool: StdPoolAllocator::new(max_pool_size),
94			row_number_pool: StdPoolAllocator::new(max_pool_size),
95			i8_pool: StdPoolAllocator::new(max_pool_size),
96			i16_pool: StdPoolAllocator::new(max_pool_size),
97			i32_pool: StdPoolAllocator::new(max_pool_size),
98			i64_pool: StdPoolAllocator::new(max_pool_size),
99			i128_pool: StdPoolAllocator::new(max_pool_size),
100			u8_pool: StdPoolAllocator::new(max_pool_size),
101			u16_pool: StdPoolAllocator::new(max_pool_size),
102			u32_pool: StdPoolAllocator::new(max_pool_size),
103			u64_pool: StdPoolAllocator::new(max_pool_size),
104			u128_pool: StdPoolAllocator::new(max_pool_size),
105			f32_pool: StdPoolAllocator::new(max_pool_size),
106			f64_pool: StdPoolAllocator::new(max_pool_size),
107
108			date_pool: StdPoolAllocator::new(max_pool_size),
109			datetime_pool: StdPoolAllocator::new(max_pool_size),
110			time_pool: StdPoolAllocator::new(max_pool_size),
111			duration_pool: StdPoolAllocator::new(max_pool_size),
112
113			uuid4_pool: StdPoolAllocator::new(max_pool_size),
114			uuid7_pool: StdPoolAllocator::new(max_pool_size),
115		}))
116	}
117
118	// Accessors for each pool type
119	pub fn bool_pool(&self) -> &StdPoolAllocator<BoolContainer> {
120		&self.bool_pool
121	}
122	pub fn string_pool(&self) -> &StdPoolAllocator<Utf8Container> {
123		&self.string_pool
124	}
125	pub fn blob_pool(&self) -> &StdPoolAllocator<BlobContainer> {
126		&self.blob_pool
127	}
128	pub fn row_number_pool(&self) -> &StdPoolAllocator<RowNumberContainer> {
129		&self.row_number_pool
130	}
131	pub fn i8_pool(&self) -> &StdPoolAllocator<NumberContainer<i8>> {
132		&self.i8_pool
133	}
134	pub fn i16_pool(&self) -> &StdPoolAllocator<NumberContainer<i16>> {
135		&self.i16_pool
136	}
137	pub fn i32_pool(&self) -> &StdPoolAllocator<NumberContainer<i32>> {
138		&self.i32_pool
139	}
140	pub fn i64_pool(&self) -> &StdPoolAllocator<NumberContainer<i64>> {
141		&self.i64_pool
142	}
143	pub fn i128_pool(&self) -> &StdPoolAllocator<NumberContainer<i128>> {
144		&self.i128_pool
145	}
146	pub fn u8_pool(&self) -> &StdPoolAllocator<NumberContainer<u8>> {
147		&self.u8_pool
148	}
149	pub fn u16_pool(&self) -> &StdPoolAllocator<NumberContainer<u16>> {
150		&self.u16_pool
151	}
152	pub fn u32_pool(&self) -> &StdPoolAllocator<NumberContainer<u32>> {
153		&self.u32_pool
154	}
155	pub fn u64_pool(&self) -> &StdPoolAllocator<NumberContainer<u64>> {
156		&self.u64_pool
157	}
158	pub fn u128_pool(&self) -> &StdPoolAllocator<NumberContainer<u128>> {
159		&self.u128_pool
160	}
161	pub fn f32_pool(&self) -> &StdPoolAllocator<NumberContainer<f32>> {
162		&self.f32_pool
163	}
164	pub fn f64_pool(&self) -> &StdPoolAllocator<NumberContainer<f64>> {
165		&self.f64_pool
166	}
167
168	pub fn date_pool(&self) -> &StdPoolAllocator<TemporalContainer<Date>> {
169		&self.date_pool
170	}
171	pub fn datetime_pool(&self) -> &StdPoolAllocator<TemporalContainer<DateTime>> {
172		&self.datetime_pool
173	}
174	pub fn time_pool(&self) -> &StdPoolAllocator<TemporalContainer<Time>> {
175		&self.time_pool
176	}
177	pub fn duration_pool(&self) -> &StdPoolAllocator<TemporalContainer<Duration>> {
178		&self.duration_pool
179	}
180
181	pub fn uuid4_pool(&self) -> &StdPoolAllocator<UuidContainer<Uuid4>> {
182		&self.uuid4_pool
183	}
184	pub fn uuid7_pool(&self) -> &StdPoolAllocator<UuidContainer<Uuid7>> {
185		&self.uuid7_pool
186	}
187
188	/// Clear all pools
189	pub fn clear_all(&self) {
190		self.bool_pool.clear();
191		self.string_pool.clear();
192		self.blob_pool.clear();
193		self.row_number_pool.clear();
194		self.i8_pool.clear();
195		self.i16_pool.clear();
196		self.i32_pool.clear();
197		self.i64_pool.clear();
198		self.i128_pool.clear();
199		self.u8_pool.clear();
200		self.u16_pool.clear();
201		self.u32_pool.clear();
202		self.u64_pool.clear();
203		self.u128_pool.clear();
204		self.f32_pool.clear();
205		self.f64_pool.clear();
206
207		self.date_pool.clear();
208		self.datetime_pool.clear();
209		self.time_pool.clear();
210		self.duration_pool.clear();
211
212		self.uuid4_pool.clear();
213		self.uuid7_pool.clear();
214	}
215
216	/// Get statistics for all pools
217	pub fn all_stats(&self) -> HashMap<String, PoolStats> {
218		let mut stats = HashMap::new();
219
220		stats.insert("bool".to_string(), self.bool_pool.stats());
221		stats.insert("string".to_string(), self.string_pool.stats());
222		stats.insert("blob".to_string(), self.blob_pool.stats());
223		stats.insert("row_number".to_string(), self.row_number_pool.stats());
224		stats.insert("i8".to_string(), self.i8_pool.stats());
225		stats.insert("i16".to_string(), self.i16_pool.stats());
226		stats.insert("i32".to_string(), self.i32_pool.stats());
227		stats.insert("i64".to_string(), self.i64_pool.stats());
228		stats.insert("i128".to_string(), self.i128_pool.stats());
229		stats.insert("u8".to_string(), self.u8_pool.stats());
230		stats.insert("u16".to_string(), self.u16_pool.stats());
231		stats.insert("u32".to_string(), self.u32_pool.stats());
232		stats.insert("u64".to_string(), self.u64_pool.stats());
233		stats.insert("u128".to_string(), self.u128_pool.stats());
234		stats.insert("f32".to_string(), self.f32_pool.stats());
235		stats.insert("f64".to_string(), self.f64_pool.stats());
236
237		stats.insert("date".to_string(), self.date_pool.stats());
238		stats.insert("datetime".to_string(), self.datetime_pool.stats());
239		stats.insert("time".to_string(), self.time_pool.stats());
240		stats.insert("duration".to_string(), self.duration_pool.stats());
241
242		stats.insert("uuid4".to_string(), self.uuid4_pool.stats());
243		stats.insert("uuid7".to_string(), self.uuid7_pool.stats());
244
245		stats
246	}
247}
248
249#[cfg(test)]
250pub mod tests {
251	use super::{allocator::PoolAllocator, *};
252
253	#[test]
254	fn test_container_pools() {
255		let pools = Pools::new(4);
256
257		// Test different pool types
258		let bool_container = pools.bool_pool().acquire(10);
259		let string_container = pools.string_pool().acquire(20);
260		let i32_container = pools.i32_pool().acquire(30);
261
262		pools.bool_pool().release(bool_container);
263		pools.string_pool().release(string_container);
264		pools.i32_pool().release(i32_container);
265
266		let all_stats = pools.all_stats();
267		assert_eq!(all_stats["bool"].available, 1);
268		assert_eq!(all_stats["string"].available, 1);
269		assert_eq!(all_stats["i32"].available, 1);
270	}
271
272	#[test]
273	fn test_clear_pools() {
274		let pools = Pools::new(4);
275
276		let container = pools.bool_pool().acquire(10);
277		pools.bool_pool().release(container);
278
279		assert_eq!(pools.bool_pool().stats().available, 1);
280
281		pools.clear_all();
282
283		assert_eq!(pools.bool_pool().stats().available, 0);
284	}
285}