zeropool 0.3.1

High-performance buffer pool with constant-time allocation, thread-safe operations, and 5x speedup over bytes crate
Documentation
## 🔍 DEEP ARCHITECTURAL ANALYSIS: ZeroPool Buffer Pool

Based on thorough code analysis, benchmark review, and architectural patterns study, here are all
identified improvements categorized by impact and complexity.

### 5. No Batch Operations API

Problem: No way to get/put multiple buffers efficiently.

Current: Users must call get() N times, locking mutex N times

Impact:

• Mutex contention in multi-threaded scenarios
• No amortized locking cost

Solution:

impl BufferPool {
pub fn get_batch(&self, sizes: &[usize]) -> Vec<Vec<u8>> {
// Lock once, get many
}

    pub fn put_batch(&self, buffers: Vec<Vec<u8>>) {
        // Lock once, put many
    }

}

Complexity: Medium | Priority: MEDIUM

---

### 7. No NUMA Awareness

Problem: Buffers allocated on one NUMA node may be used on another.

Impact:

• Cross-NUMA memory access is 2-3x slower
• Critical for 32+ core servers

Solution:

// Pin shards to NUMA nodes
fn calculate_num_shards(num_cpus: usize) -> usize {
let numa_nodes = detect_numa_nodes();
numa_nodes.max(4).next_power_of_two() // Align to NUMA topology
}

Complexity: High | Priority: LOW (only for large servers)

---

## 🏗️ ARCHITECTURAL IMPROVEMENTS (Structural)

### 8. Missing Metrics/Observability

Problem: No way to measure hit rates, contention, or effectiveness.

Impact:

• Can't diagnose performance issues
• No visibility into TLS hit rate vs shared pool hit rate

Solution:

pub struct PoolStats {
pub tls_hits: AtomicUsize,
pub shared_hits: AtomicUsize,
pub allocations: AtomicUsize,
pub contention_events: AtomicUsize,
}

impl BufferPool {
pub fn stats(&self) -> PoolStats { ... }
pub fn hit_rate(&self) -> f64 { ... }
}

Complexity: Low | Priority: MEDIUM

---

### 9. No Async/Await Support

Problem: Sync-only API doesn't work well with async runtimes.

Impact:

• Holding mutex across await points causes deadlocks
• Tokio users can't use this efficiently

Solution:

# [cfg(feature = "async")]

impl BufferPool {
pub async fn get_async(&self, size: usize) -> Vec<u8> {
// Use tokio::sync::Mutex or async-aware locks
}
}

Complexity: High | Priority: LOW (unless targeting async workloads)

---

### 10. Hardcoded Vec - Not Generic

Problem: Only works with Vec<u8>, can't pool other types.

Location: Throughout (e.g., line 437)

Impact:

• Can't pool String, custom buffers, or other allocations
• Limits reusability

Solution:

pub struct BufferPool<T = Vec<u8>> {
shards: Arc<Vec<Mutex<Vec<T>>>>,
factory: Arc<dyn Fn(usize) -> T>,
}

Complexity: High | Priority: LOW

---

### 11. No Memory Budget Enforcement

Problem: Pool can grow unbounded until hitting per-shard limits.

Location: Line 688 (only checks per-shard limit)

Impact:

• No global memory cap
• Can OOM if many threads cache buffers

Solution:

pub struct Builder {
max_total_memory: Option<usize>, // e.g., 1GB total
}

// In put(): check global budget before accepting buffer
if self.total_memory.load(Relaxed) + buffer.capacity() > self.config.max_total_memory {
return; // Reject buffer
}

Complexity: Medium | Priority: MEDIUM

---