跪拜 Guibai
← All articles
Frontend · Architecture · Interview

Web Workers Don't Make JavaScript Faster — They Keep the UI Thread Breathing

By 李剑一 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Developers who treat Workers as a general speed-up will ship slower code. The right use is isolating tasks that would otherwise block the UI, not micro-optimizing every calculation.

Summary

A Web Worker runs scripts in a separate thread with its own V8 isolate and event loop, communicating with the main thread asynchronously via postMessage. The payoff is a responsive UI during heavy computation, not raw speed. Spinning up a Worker incurs a cold-start cost of tens to hundreds of milliseconds as the browser creates a new JS environment, loads, parses, and compiles the worker script. Every postMessage round-trip adds further overhead, even for small payloads. For lightweight calculations, the main thread finishes faster because it skips these setup and communication taxes. The real value is keeping DOM rendering and interaction smooth when work is genuinely heavy. Multiple Workers can parallelize work, but Chrome caps them around eight, and the OS scheduler will queue excess threads. Each Worker also consumes significant memory through its isolated heap. A practical ceiling is Math.max(2, navigator.hardwareConcurrency - 1) to avoid thrashing CPU and memory.

Takeaways
Web Workers run in a separate thread with their own V8 isolate and event loop, communicating with the main thread asynchronously via postMessage and onmessage.
Creating a Worker has a cold-start cost of tens to hundreds of milliseconds: the browser spawns an OS thread, creates an independent JS environment, and loads and compiles the worker script.
Every postMessage call incurs communication overhead, even for small objects, and this cost repeats on each message exchange.
Ordinary computations often run faster on the main thread because they avoid Worker creation and messaging overhead; Workers are for preventing UI blockage, not for raw speed.
Browsers cap the number of Workers (Chrome allows roughly eight), and exceeding logical core counts triggers OS thread scheduling that degrades performance.
Each Worker carries significant memory overhead from its independent V8 isolate, so spawning many Workers can bloat memory usage.
A safe Worker pool size is Math.max(2, navigator.hardwareConcurrency - 1), reserving cores for the OS and other browser tasks.
Dedicated Workers are tied to a single page context; closing the page or calling worker.terminate() destroys them.
Conclusions

The mental model of 'Worker equals faster' is backwards: the main thread often wins on speed for small tasks because it skips the cold-start and serialization tax. Workers are a UI-responsiveness tool, not a performance accelerator.

Browser thread limits and per-isolate memory costs make Worker pools a constrained resource, not an elastic one. Over-provisioning punishes performance through OS scheduling and memory pressure, which is the opposite of what a naive 'just parallelize it' approach expects.

The postMessage bridge is a bottleneck that turns fine-grained parallelism into an anti-pattern. The overhead per message means batching work into fewer, larger messages is essential, yet the API's simplicity hides this.

navigator.hardwareConcurrency offers a logical core count, but the usable Worker ceiling is lower because the OS, browser, and other tabs all compete for the same physical threads. The recommended formula acknowledges this contention explicitly.

Concepts & terms
Web Worker (Dedicated Worker)
A browser API that runs JavaScript in a separate background thread with its own V8 isolate and event loop. It cannot access the DOM and communicates with the main thread asynchronously via postMessage. Tied to a single page context and destroyed when the page closes.
V8 Isolate
An independent instance of the V8 JavaScript engine with its own heap and execution context. Each Web Worker gets its own isolate, which is why Workers cannot share JS object memory directly and why creating many Workers consumes significant RAM.
navigator.hardwareConcurrency
A browser API that returns the number of logical processor cores available on the user's device. Used to determine a sensible upper bound for Worker pools, though the practical limit is lower due to OS and browser overhead.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗