ZeroPool
A high-performance buffer pool for Rust — Performance First
Why ZeroPool?
ZeroPool is a high-performance buffer pool that prioritizes speed above all else:
- Lock-free architecture:
crossbeam::ArrayQueueper size class — no mutexes - Size-class bucketing: 8 power-of-two classes (4KB→64MB) for O(1) class selection
- Thread-local caching: Per-class LIFO caches with magazine-style batch transfer
- Pool isolation: Unique pool IDs prevent TLS cache cross-contamination
- Auto-configured: Adapts to your CPU topology for optimal multi-threaded performance
Quick Start
use BufferPool;
let pool = new;
// Get a buffer (returns RAII guard)
let mut buffer = pool.get; // 1MB
// Use it — Deref<Target = [u8]> for safe slice access
buffer = 42;
// Buffer automatically returned to pool when dropped
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] │
└────────────────┘
Fast path: TLS cache pop (lock-free, ~8–30ns)
Medium path: Magazine-style batch refill from shared pool (CAS-based)
Cold path: Fresh allocation via SizeClass::allocate
Configuration
use BufferPool;
let pool = builder
.tls_cache_size // Buffers per class per thread
.max_buffers_per_class // Max pooled per class in shared pool
.min_buffer_size // Pool buffers ≥ 4KB
.batch_size // Magazine transfer size
.build;
Defaults (auto-configured based on CPU count):
- TLS cache: 2–8 buffers per class per thread
- Max per class: 32–128 buffers
- Min buffer size: 4KB
- Batch size: half of TLS cache (min 2)
Memory Pinning
Lock buffer memory in RAM to prevent swapping (performance optimization):
use BufferPool;
let pool = builder
.pinned_memory
.build;
Useful for high-performance computing or real-time systems. May require elevated privileges on some systems. Falls back gracefully if pinning fails.
Pre-allocation
Warm up the pool before high-throughput operations:
let pool = builder.min_buffer_size.build;
pool.preallocate; // 16 × 64KB buffers
Thread Safety
BufferPool is Clone and thread-safe (Arc<Inner> internally):
let pool = new;
for _ in 0..4
Ownership and Pool Return
When a PooledBuffer is dropped, the buffer returns to the pool. Use into_inner() to extract the Vec<u8> without returning it:
let pool = new;
// Normal: returns to pool on drop
// Extract ownership — does NOT return to pool
let buffer = pool.get;
let vec: = buffer.into_inner;
Use Cases
- Data processing: ETL pipelines, log processing, analytics
- Network servers: HTTP, gRPC, WebSocket servers with high throughput
- File I/O: Async file loading with io_uring, tokio, async-std
- LLM inference: Fast checkpoint loading and model serving
- Real-time systems: Low-latency buffer management
- Big data: High-throughput data streaming and processing
Comparison with Alternatives
| Feature | ZeroPool | bytes::BytesMut | Lifeguard | Sharded-Slab |
|---|---|---|---|---|
| Lock-free pool | ArrayQueue (CAS) | No | No | Partial |
| Size classes | 8 power-of-two | No | No | No |
| TLS caching | Per-class LIFO | No | No | No |
| Batch transfer | Magazine-style | No | No | No |
| Auto-configured | CPU-aware | Manual | Manual | Manual |
| Pool isolation | Unique IDs | N/A | No | N/A |
Performance
Run benchmarks:
License
Dual licensed under Apache-2.0 or MIT.
Contributing
PRs welcome! Please include benchmarks for performance changes and ensure all tests pass:
Changelog
See CHANGELOG.md for version history.
Credits
Built for the Rust community. Inspired by TCMalloc size-class design, Bonwick magazine-layer research, and modern lock-free allocator techniques.