Zero-Pool: Consistent High-Performance Thread Pool
A FIFO MPMC thread pool with a single global queue and cooperative memory reclamation.
Key Features:
- Zero locks - lock-free
- Zero queue limit - unbounded
- Zero channels - no std/crossbeam channel overhead
- Zero virtual dispatch - function pointer dispatch avoids vtable lookups
- Zero core spinning - all event-based
- Zero result transport cost - tasks write directly to caller-provided memory
- Zero per worker queues - single global queue structure = perfect workload balancing
- Zero external dependencies - standard library only and stable rust
Using a result-via-parameters pattern means workers place results into caller provided memory, removing thread transport overhead. The single global queue structure ensures optimal load balancing without the complexity of work-stealing or load redistribution algorithms.
Because the library uses raw pointers, you must ensure parameter structs (including any pointers they contain) remain valid until task completion, and that your task functions are thread-safe.
This approach allows complete freedom to optimise multi-threaded workloads any way you want.
Notes
- TaskFuture is easily clonable, but
wait()/wait_timeout()must be called from the thread that submitted the task.is_complete()is safe to call from any thread. - Zero-Pool supports both explicitly creating new thread pools (
ZeroPool::new,ZeroPool::with_workers) and using the global instance (zero_pool::global_pool). - Task functions take a single parameter (e.g.
&MyTaskParams).
Benchmarks (AMD 5900X, Linux 7.1)
rayon_heavy_compute ... bench: 4,840,907.85 ns/iter
zeropool_heavy_compute ... bench: 4,438,862.85 ns/iter
rayon_individual_tasks ... bench: 779,474.28 ns/iter
zeropool_individual_tasks ... bench: 1,043,626.32 ns/iter
rayon_task_overhead ... bench: 30,815.31 ns/iter
zeropool_task_overhead ... bench: 31,169.77 ns/iter
Example Usage
Submitting a Single Task
use ZeroPool;
let pool = new;
let mut result = 0u64;
let task = CalculationParams ;
let future = pool.submit_task;
future.wait;
println!;
Submitting Uniform Batches
Submits multiple tasks of the same type to the thread pool.
use ZeroPool;
let pool = new;
let mut results = vec!;
let tasks: = results.iter_mut.enumerate.map.collect;
let future = pool.submit_batch;
future.wait;
println!;
Submitting Multiple Independent Tasks
You can submit individual tasks and uniform batches in parallel:
use ZeroPool;
// Define first task type
// Define second task type
let pool = new;
// Individual task
let mut single_result = 0u64;
let single_task_params = ComputeParams ;
// Uniform batch
let mut batch_results = vec!;
let batch_task_params: = batch_results.iter_mut.enumerate
.map
.collect;
// Submit all batches
let future1 = pool.submit_task;
let future2 = pool.submit_batch;
// Wait on them in any order; completion order is not guaranteed
future1.wait;
future2.wait;
println!;
println!;
Using the Global Pool
If you prefer to share a single pool across your entire application, call the global accessor. The pool is created on first use and lives for the duration of the process.
use global_pool;
let pool = global_pool;
let mut result = 0u64;
let params = ExampleParams ;
pool.submit_task.wait;