924-work-stealing — Work Stealing
Tutorial
The Problem
A fixed thread pool with a single shared work queue can become a bottleneck: all workers contend for the same lock. Work-stealing distributes this: each worker has its own local queue; when idle, a worker "steals" tasks from another worker's queue. This approach was invented for the Cilk parallel runtime at MIT and is used in Java's ForkJoinPool, .NET's ThreadPool, Go's goroutine scheduler, and Rust's rayon. Local queues use lock-free algorithms for pushes; stealing requires only occasional locking. The result is near-linear scaling on multi-core processors for divide-and-conquer workloads.
🎯 Learning Outcomes
Domainslib and Moonpool for parallel work stealingCode Example
#![allow(clippy::all)]
// Placeholder — Work StealingKey Differences
rayon provides work-stealing transparently via par_iter() — no manual thread management; OCaml requires explicit Domainslib API calls.rayon::join(f, g) is the idiomatic parallel divide-and-conquer entry point; OCaml Task.async is the equivalent.rayon is the production Rust solution for CPU-bound parallel work; OCaml's parallel ecosystem is still maturing (OCaml 5 is relatively new).OCaml Approach
OCaml 5 introduces Domain.spawn for true parallelism. Domainslib builds work-stealing on top of domains. Task.pool creates a pool; Task.async pool f submits a task; Task.await retrieves the result. Moonpool provides an alternative with configurable scheduling. OCaml's cooperative (Lwt, Eio) runtimes do not benefit from work-stealing (they run on one domain unless using Eio.Fiber). The biggest difference: OCaml 5 domains are heavyweight compared to Rust threads.
Full Source
#![allow(clippy::all)]
// Placeholder — Work StealingDeep Comparison
924-work-stealing — Language Comparison
std vs tokio
| Aspect | std version | tokio version |
|---|---|---|
| Runtime | OS threads via std::thread | Async tasks on tokio runtime |
| Synchronization | std::sync::Mutex, Condvar | tokio::sync::Mutex, channels |
| Channels | std::sync::mpsc (unbounded) | tokio::sync::mpsc (bounded, async) |
| Blocking | Thread blocks on lock/recv | Task yields, runtime switches tasks |
| Overhead | One OS thread per task | Many tasks per thread (M:N) |
| Best for | CPU-bound, simple concurrency | I/O-bound, high-concurrency servers |
Exercises
find_any that searches for a value across N worker threads, cancelling others when found.