A little known annoying detail of web workers is that passing large data to them via postMessage is incredibly slow. The browser has to convert your javascript object into some sort of internal binary format and it slows down the thread that's doing the sending.
Depends on the type of large data, but since 2011 there's "Transferable" [1], where objects like ArrayBuffer, MessagePort, and ImageBitmap can be transferred with a low overhead [2]. Now, if you're passing large arbitrary object graphs, you're out of luck. [1] https://developers.google.com/web/updates/2011/12/Transferab... [2] https://developer.mozilla.org/en-US/docs/Web/API/Worker/post...
Web Workers API
31–40 of 47 posts
Re: Web Workers API
#32The fact that creating a worker requires you to pass a module (file) name makes them extremely unergonomic to use. This is clearly visible in the lack of any library ecosystem around them. We don't have any highly used threadpool or executor libraries using workers. Everyone seems to be manually setting up a worker and setting up the job scheduling logic from scratch. All the boilerplate and restrictions really restr…
Re: Web Workers API
#33Earlier quoted context omitted.
Depends on the type of large data, but since 2011 there's "Transferable" [1], where objects like ArrayBuffer, MessagePort, and ImageBitmap can be transferred with a low overhead [2]. Now, if you're passing large arbitrary object graphs, you're out of luck. [1] https://developers.google.com/web/updates/2011/12/Transferab... [2] https://developer.mozilla.org/en-US/docs/Web/API/Worker/post...
Any libraries that make this nicer/easier to do instead of rewriting the same thing over and over?
Re: Web Workers API
#34The fact that creating a worker requires you to pass a module (file) name makes them extremely unergonomic to use. This is clearly visible in the lack of any library ecosystem around them. We don't have any highly used threadpool or executor libraries using workers. Everyone seems to be manually setting up a worker and setting up the job scheduling logic from scratch. All the boilerplate and restrictions really restr…
Can anybody explain how did this ever make it into the official spec and the default implementation?
The browser will make a network call to fetch your Web Worker .js file on every instantiation of your Web Worker. Instantiations of the same Web Worker "module" aren't cached, so in a thread-pool scenario your browser would be fetching the same file over and over again.
What were the people designing this even thinking? This is so wasteful and frustrating. The API simply sucks.
Re: Web Workers API
#35The fact that creating a worker requires you to pass a module (file) name makes them extremely unergonomic to use. This is clearly visible in the lack of any library ecosystem around them. We don't have any highly used threadpool or executor libraries using workers. Everyone seems to be manually setting up a worker and setting up the job scheduling logic from scratch. All the boilerplate and restrictions really restr…
> "The fact that creating a worker requires you to pass a module (file) name makes them extremely unergonomic to use." Can anybody explain how did this ever make it into the official spec and the default implementation? The browser will make a network call to fetch your Web Worker .js file on every instantiation of your Web Worker. Instantiations of the same Web Worker "module" aren't cached, so in a thread-pool scen…
This and service workers. Both are... weird, to say the least
Re: Web Workers API
#36The fact that creating a worker requires you to pass a module (file) name makes them extremely unergonomic to use. This is clearly visible in the lack of any library ecosystem around them. We don't have any highly used threadpool or executor libraries using workers. Everyone seems to be manually setting up a worker and setting up the job scheduling logic from scratch. All the boilerplate and restrictions really restr…
> "The fact that creating a worker requires you to pass a module (file) name makes them extremely unergonomic to use." Can anybody explain how did this ever make it into the official spec and the default implementation? The browser will make a network call to fetch your Web Worker .js file on every instantiation of your Web Worker. Instantiations of the same Web Worker "module" aren't cached, so in a thread-pool scen…
For example, FileReader API is async in the main thread. There's an equivalent FileReaderSync for sync operations but that is only available in Web Workers. Why isn't FileReaderSync available on the main thread? Because the designers didn't want people to do things that would block the main thread.
The Web Worker argument probably went along the lines of "If we allow users to pass arbitrary function objects, they may try to do something that accesses local variables from the site where the worker is created. That is obviously an error, so we should design the API so that it can't happen. Creating a separate script creates a clear mental separation and avoids that class of error"
Re: Web Workers API
#37The fact that creating a worker requires you to pass a module (file) name makes them extremely unergonomic to use. This is clearly visible in the lack of any library ecosystem around them. We don't have any highly used threadpool or executor libraries using workers. Everyone seems to be manually setting up a worker and setting up the job scheduling logic from scratch. All the boilerplate and restrictions really restr…
Personally I've written my own libraries for abstracting all this away and I'm having a blast working with workers now, maybe check them out:
- WorkTank [1]: This abstracts away the difference between browser workers and Node worker threads, it makes it easy to make worker pools, and it can transfer simple functions to a worker at runtime too.
- WorkTank loader: This abstracts away loading asynchronous function from a worker basically, you just add ".worker" to your file name and that file and all its dependencies are transparently moved to a worker (or worker pool), all the rest of the app (TS types for example) won't even notice anything happened, it just works, transparently.
You might want to check out the more popular "comlink" library too, although it didn't work for me for whatever reason when I tried it, and it doesn't support worker pools I believe.
Re: Web Workers API
#38Earlier quoted context omitted.
> "The fact that creating a worker requires you to pass a module (file) name makes them extremely unergonomic to use." Can anybody explain how did this ever make it into the official spec and the default implementation? The browser will make a network call to fetch your Web Worker .js file on every instantiation of your Web Worker. Instantiations of the same Web Worker "module" aren't cached, so in a thread-pool scen…
> Can anybody explain how did this ever make it into the official spec and the default implementation? This and service workers. Both are... weird, to say the least
Failing to account for the thread-pool scenario, as an example, is just mind boggling.
Re: Web Workers API
#39Re: Web Workers API
#40The fact that creating a worker requires you to pass a module (file) name makes them extremely unergonomic to use. This is clearly visible in the lack of any library ecosystem around them. We don't have any highly used threadpool or executor libraries using workers. Everyone seems to be manually setting up a worker and setting up the job scheduling logic from scratch. All the boilerplate and restrictions really restr…
Basically, any sort of work scheduling that you would like to do to queue high-priority messages, or have workers share a pool of work, is impossible to build with the onmessage-style of WebWorkers. It feels like an API made by someone who had read about threads once, rather than someone who's built an actual many-workers processing system like this. The event loop being unpumpable from user code feels like a giant kick in the face.
My workaround for this was to kill workers working on low-priority items, relaunch them, and resort the queue, but that all feels like a mess. Also, at some point a Chrome update made this strategy crash. I ended up just removing the WebWorker code; more trouble than it was worth for marginal code improvements.
I know that SAB and atomics add new low-level primitives to support this, but SAB is still poorly supported on widely deployed platforms. And you still need to do the serialization yourself.