pub struct ZeroPool { /* private fields */ }Expand description
A user-space byte allocator with size-class bucketing and thread-local caching.
§Architecture
Thread 1 Thread 2 Thread N
┌────────────┐ ┌────────────┐ ┌────────────┐
│ TLS Cache │ │ TLS Cache │ │ TLS Cache │ ← Lock-free
│ [class 0] │ │ [class 0] │ │ [class 0] │ per-class
│ [class 1] │ │ [class 1] │ │ [class 1] │ LIFO caches
│ ... │ │ ... │ │ ... │
└─────┬──────┘ └─────┬──────┘ └─────┬──────┘
│ batch │ batch │ batch
└──────────┬───────┴───────────────────┘
│
┌───────▼────────┐
│ Shared Pool │
│ (lock-free) │
│ │
│ [4KB queue] │ ArrayQueue per class
│ [16KB queue] │ CAS-based push/pop
│ [64KB queue] │ No mutex needed
│ [256KB queue] │
│ [1MB queue] │
│ [4MB queue] │
│ [16MB queue] │
│ [64MB queue] │
└────────────────┘Implementations§
Source§impl ZeroPool
impl ZeroPool
Sourcepub fn new() -> Self
pub fn new() -> Self
Create a new allocator with system-aware defaults.
Chain configuration methods to customize before use:
use zeropool::ZeroPool;
// Defaults
let pool = ZeroPool::new();
// Custom
let pool = ZeroPool::new()
.min_buffer_size(4096)
.tls_cache_size(8)
.max_buffers_per_class(64)
.batch_size(4)
.track_stats(true);Sourcepub fn allocator(self, alloc: impl Allocator) -> Self
pub fn allocator(self, alloc: impl Allocator) -> Self
Set a custom allocator for buffer creation.
Default: HeapAllocator (standard Vec::with_capacity).
use zeropool::{Allocator, ZeroPool};
struct MyAllocator;
impl Allocator for MyAllocator {
fn allocate(&self, capacity: usize) -> Vec<u8> {
Vec::with_capacity(capacity)
}
}
let pool = ZeroPool::new().allocator(MyAllocator);Sourcepub fn min_buffer_size(self, size: usize) -> Self
pub fn min_buffer_size(self, size: usize) -> Self
Set the minimum buffer size to keep in the pool.
Buffers smaller than this are discarded on dealloc. Default: 4KB
Sourcepub fn tls_cache_size(self, size: usize) -> Self
pub fn tls_cache_size(self, size: usize) -> Self
Set the number of buffers kept in thread-local cache per size class.
Higher values reduce shared pool access but increase per-thread memory.
Also recomputes batch size (half of TLS cache, min 2) unless
.batch_size() is called afterwards to override.
Default: 2–8 based on CPU count
Sourcepub fn max_buffers_per_class(self, count: usize) -> Self
pub fn max_buffers_per_class(self, count: usize) -> Self
Set the maximum number of buffers per size class in the shared pool.
Default: 32–128 based on CPU count
Sourcepub fn pinned_memory(self, enabled: bool) -> Self
pub fn pinned_memory(self, enabled: bool) -> Self
Enable pinned memory (mlock) for allocated buffers.
Locks buffers in RAM to prevent swapping. Default: false
Sourcepub fn batch_size(self, size: usize) -> Self
pub fn batch_size(self, size: usize) -> Self
Set the batch size for TLS ↔ shared pool transfers.
When a thread-local cache misses, this many buffers are moved at once from the shared pool (magazine-style). Default: half of TLS cache size (min 2)
Sourcepub fn track_stats(self, enabled: bool) -> Self
pub fn track_stats(self, enabled: bool) -> Self
Enable or disable runtime statistics tracking.
Disabled by default because hot-path atomic counters are measurable
overhead in tight allocation loops. Enable this when you need
stats() to report allocation counters.
Sourcepub fn alloc(&self, size: usize) -> Buf<'_> ⓘ
pub fn alloc(&self, size: usize) -> Buf<'_> ⓘ
Allocate a buffer of at least size bytes.
Returns a Buf that automatically deallocates back
to the pool on drop.
§Performance
- Fastest: TLS cache pop (lock-free, ~24ns)
- Fast: Batch refill from shared pool (lock-free CAS)
- Cold: Fresh allocation via the configured
Allocator
§Example
use zeropool::ZeroPool;
let pool = ZeroPool::new();
let mut buf = pool.alloc(1024);
buf[0] = 42;Sourcepub fn warm(&self, count: usize, size: usize)
pub fn warm(&self, count: usize, size: usize)
Warm up the pool by pre-allocating buffers for the given size class.
§Example
use zeropool::ZeroPool;
let pool = ZeroPool::new().min_buffer_size(0).track_stats(true);
pool.warm(16, 64 * 1024); // 16 × 64KB buffersSourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Total number of buffers across all shared size classes.
Does not include thread-local cached buffers.
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Whether all shared size classes are empty.
Does not check thread-local caches.
Sourcepub fn drain(&self)
pub fn drain(&self)
Drain all buffers from all shared size classes.
Thread-local caches are NOT cleared.
Sourcepub fn stats(&self) -> Stats
pub fn stats(&self) -> Stats
Point-in-time snapshot of allocator statistics.
§Example
use zeropool::ZeroPool;
let pool = ZeroPool::new().min_buffer_size(0).track_stats(true);
let buf = pool.alloc(4096);
drop(buf);
let s = pool.stats();
assert_eq!(s.gets, 1);
assert_eq!(s.puts, 1);
println!("{s}");Sourcepub fn reset_stats(&self)
pub fn reset_stats(&self)
Reset all performance counters to zero.