“Off The Main Thread”

Avatar of Chris Coyier
Chris Coyier on (Updated on )

JavaScript is what they call “single-threaded.” As Brian Barbour puts it:

This means it has one call stack and one memory heap.

We all feel a symptom of that regularly in the form of performance jank and non-interactivity on elements or entire sites. If we give JavaScript lots of jobs and it gets really busy doing them, then it’s not doing other things, like, say, handling our event handlers quickly.

There has been an interesting point/counter-point combo recently along these lines.

Das Surma has been advocating for moving as much JavaScript off the main thread as you possibly can. In fact, when it comes to using Web Workers, he suggests:

You should always use Web Workers.

Web Workers being the primary way to run JavaScript off the main thread. Paul Lewis likens the problem to The 9am Rush Hour:

The worst time of day to travel. For many it’s not possible to travel at any other time of day because they need to get to work by 9am.

This is exactly what a lot of web code looks like today: everything runs on a single thread, the main thread, and the traffic is bad. In fact, it’s even more extreme than that: there’s one lane from the city center to the outskirts, and quite literally everyone is on the road, even if they don’t need to be at the office by 9am.

I also like how Surma compares other languages in how they often call “main thread” the “UI thread”. If what you are doing is UI-related, do it on the main thread; if it’s not, do it off the main thread. He gets into this on a good episode of The Web Platform Podcast – 194: Off the Main Thread. I could see that being a positive change in the attitude and thinking of JavaScript developers.

An example of getting something off the UI thread: State management.

David Gilbertson must have read that and wrote:

I saw an article recently making the case that updating a Redux store was a good candidate for Web Workers because it’s not UI work (and non-UI work doesn’t belong on the main thread). Chucking the data processing over to a worker thread sounds sensible, but the idea struck me as a little, umm, academic.

David’s main point, it seems to me, is that some of the hefty JavaScript things we need to do are in response to user-initiated actions where the user needs to wait for things to finish anyway, so an unresponsive UI during that time is OK. But for anything that isn’t user-initiated — and takes longer than say 100ms — he agrees a Web Worker is helpful.

(Looking at that 100ms thing, it’s worth noting that a major point Surma is making is that the world is full of low-end phones — and who knows what 100ms on a high-end phone is when translated to on a low-end phone.)

The big trick in getting things off the main thread in JavaScript is using Web Workers. It’s not a hack or anything, Web Workers are quite literally the native API for bringing multiple background threads to JavaScript. Similar to a Service Worker, they are usually in another file:

var myWorker = new Worker('worker.js');

But they don’t have to be – you can inline them or use a lib. The API isn’t awful, but it’s not amazing either. Surma has a library for that: Comlink.

Surma’s crusade on this is quite the long term effort. It was a feature at 2018’s Chrome Summit with A Quest to Guarantee Responsiveness: Scheduling On and Off the Main Thread and again in 2019 with The main thread is overworked & underpaid, but this time with nearly six times the views at the time of this update:

And he’s not alone. Here’s Alex MacArthur on adjusting his thinking about event handlers to accommodate doing things off thread.