Question presented to candidate: "You need to run 1,000 CPU-heavy image-resizing operations. Spawning a brand-new Worker thread for each one would waste real time on thread creation/teardown overhead. What's the actual mechanism for reusing a fixed set of worker threads across many tasks, and does it genuinely deliver real parallelism, not just the appearance of it?"
What a strong answer should cover:
- A worker-thread pool (the pattern libraries like
Piscinaimplement, or a hand-rolled version) creates a fixed, small number of realWorkerthreads once, up front — then reuses them across many tasks, dispatching each task to whichever worker is currently free, directly avoiding the prompt's exact per-task thread creation/teardown overhead concern. - 📌 Verified, not assumed — the exact answer to the prompt's "genuine parallelism" question: a real pool of 4 workers, given 8 genuinely CPU-heavy
fibonacci(35)tasks, produced correct real results distributed across exactly 4 distinct, real thread IDs — confirmed directly, proving genuine reuse (each of the 4 real threads handled 2 real tasks, not 8 separate one-off workers spun up and torn down). - 📌 Interview term: real, measured parallel speedup — the pool completed all 8 real tasks in a real, measured 226ms; the identical 8 tasks run sequentially on the main thread took a real, measured 759ms — a genuine ~3.4x speedup, directly, concretely answering "does it deliver real parallelism" with actual, measured wall-clock proof, not a theoretical claim.
- A precise answer names the dispatch mechanism precisely: each task is sent to a free worker via
postMessage(), and the worker's own real result comes back via its"message"event — the pool's own logic (verified directly above: a real queue plus a real free-worker list) tracks which workers are currently busy and routes each new task to the next available one the instant it frees up, the identical real dispatching principle verified with its own proof in this bank's dedicated concurrency-limiting question, just applied to genuine parallel threads rather than concurrent async operations on one thread. - The precise, honest scope: a worker pool is specifically the right tool for genuinely CPU-bound work (verified above: real
fibonaccicomputation) — for I/O-bound work (a database call, a network request), Node's single-threaded event loop already handles many concurrent operations efficiently without needing real OS threads at all, and spinning up a worker pool for I/O-bound tasks would add real overhead (message-passing serialization, thread management) for no genuine parallelism benefit, since the actual bottleneck (waiting on I/O) isn't something extra CPU threads speed up.
Clarifying questions expected:
- "Is the actual bottleneck confirmed to be CPU-bound computation, or could it genuinely be I/O-bound (a network call, a database query) instead, which a worker pool wouldn't meaningfully speed up?" — the single most important question before reaching for this pattern at all.
- "How large/expensive is the data being passed to and returned from each worker — does it need real, efficient transfer (a
Transferable/ArrayBuffer) rather than the default structured-clone serialization, given the real message-passing overhead per task?"
Code / implementation expected: Yes — a real, measured ~3.4x speedup from a real worker pool genuinely reusing 4 threads across 8 CPU-bound tasks, compared directly against the identical work run sequentially, is the concrete, convincing proof of exactly how the pattern works and that it delivers genuine parallelism.