Hacker Read top | best | new | newcomments | leaders | about | bookmarklet login

Trust me, we tried. But as long as image decoding blocks the main thread (Webkit), you are helpless to update the UI thread at a fast pace. We even tried decoding images in a web worker and sending the result back to the main thread - but decoding in JS is very slow so general application throughput suffers (not through fault of JS itself, but because JS lacks SIMD which image decoding algorithms use in order to decode images quickly).

But running React in a web worker is still a really great idea. There would just be a lot of little edge cases to handle (like when you click a link - you need to prevent default of navigation, then send that link click to the web worker to see if your app wants to prevent default, if not, force the redirect back on the main thread). Having tight control over text editing might be challenging as well. These are difficulties, but I suspect they are a fixed set of challenges that are worth the increased parallelism in an increasingly multicore world.

But are web workers currently The Solution To All Our Mobile App Needs? No, but they're a great tool that are highly underutilized by JS developers, and that React is uniquely positioned to take advantage of.



sort by: page size:

FWIW I believe that web worker adoption is more limited by tooling/knowledge than APIs. Web developers haven't thought about thread safety for decades (at least for those who have been around for that long) so it's more of a mental leap for web developers to think in terms of multiple threads.

I had some promising (at the very least interesting) results with react-native-dom which runs all of React's reconciliation & your own business logic in a web worker: https://rndom-movie-demo.now.sh. I'll fully admit there's a lot more exploration/experimentation left to be done in this space though.


Until "web workers" are generally supported by common browsers, there is no way to run more than on bit of Javascript at a time in any given tab. As all the code is running in a single thread it will only use one CPU core (or if the scheduler bounces the browser process between cores it will use at most one core/second worth of CPU resource per second).

Depending on the how much cross talk there would be between the threads, web workers might not be adequate for some algorithms anyway as the message passing (the only way web workers can communicate, there is no "shared memory" access or other such short cuts to communication) could add noticeable latency. Caveat: I've not used them for anything myself so I don't know if any such latency is large enough to be an issue.

You can create multi-threaded code using web workers, but you exclude your app from browsers that don't support them. The major laggard on the desktop is IE, which is due to gain support for them in version 10. As far as I know the only current mobile browser that supports them is Safari under iOS5, apparently they were present in Android's browser but removed/disabled in recent releases.


> Yes, you have webworkers for multi threaded development. They're basically independent applications which run on different threads and you pass messages (which are simply objects) between them. The browsers themselves are also moving their layout and rendering engines to be multithreaded.

Yes I'm actually referring to this. The programming model. Workers are great if you can divide and conquer the problem and offload (exactly what you have mentioned). But the messaging payload would be high under some circumstances when you have to repetitively copy duplicate a lot of data to start a worker. I don't have hands-on experience with web workers but I think it is unlikely to solve the messaging overhead without introducing channels/threads. Workers are more like processes. And currently they don't have Copy-On-Write. Of course we may see improvements over time, but this is to gradually reinvent all the possible wheels from an operating system, in order to be as performant as an OS.

> A well designed app would do very little on the UI thread

I partially agree. It may do little, but in turn, the consequence may be huge. This is because DOM is not a zero-cost abstraction of a UI. It does not understand what the programmer really want to do if, say, he/she constantly ramping the transparency of a 1px div. Too much happens before the cursor blink is reflected onto a framebuffer, compared to a "native" GUI program. I think it will be very helpful if the DOM can be declarative as in XAML, where you can really say <ComplexGUIElement ... /> without translating them eventually into barebone bits. Developers are paying too much (the consequence) to customize this representation.

> Whatever the speedup would be the speedup the users would likely not notice or will only notice a slight improvement.

There won't be a faster-than-light word processor but I really want it to: 1. Start immediately (say 10ms instead of 1000ms) when I call it up 2. Response immediately when I interact (say 1ms instead of 100ms) 3. Reduce visual distractions until we get full 120fps. Don't do animations if we don't have 120fps. 4. If the above requirements can always be satisfied by upgrading to a better computer.

The speedup will guarantee 4) and make the performance scalable. But currently the web apps lag no matter I use a cellphone or a flagship workstation. This clearly indicates that the performance of a web app does not scale linearly with computation power, and this is not about how much javascript is executed (that part will scale I believe).


I was playing around with Web Workers and saw a bit of a gap when it came to image manipulation. A lot of examples provided for browser based image manipulation relied on the canvas api which workers do not have an interface to.

Using the JPEG decoder from the Mozilla pdf.js project as well as a JPEG encoder from Adobe I demonstrate how you can do somewhat heavy lifting in the front end for images without locking the main thread.

It works in Chrome for the moment but should work in any browser that allows FileReader in the workers (FireFox only allows FileReaderSync) but I could get that to behave nicely so FireFox is unsupported for now.

Also the output image will probably be artifacted but I wasn't focusing on quality just yet.

One interesting thing seems to be that there is very little difference in processing time between the single worker vs. multiple workers examples.


Even just JavaScript Web Workers can be really helpful for doing heavy compute outside of the UI thread. JavaScript is pretty fast, it just needs to be unblocked. I used them once to sort a six-digit array of objects client side, while keeping the UI snappy (it took a couple seconds to process, but the UI was responsive the whole time)

Of course for some tasks you'll still need more than that, which very well may have been true for the OP, but benchmarking is good etc


Web Workers are true threads, it's just the shared memory part that's missing. I think we will have to introduce some form of it at some point, and there are ways to do it but there's definitely a lot more research required (think about only allowed a typed array to be shared, with atomic reads/writes). I don't really know what's going to happen with this feature, and it is the one single thing that's going to be hard to do in JS, but I think we can solve it and there's really nothing else missing (or isn't planned to be implemented).

That's something I've been thinking about. Webworkers don't have direct access to the Canvas though, but it seems like you can work around that by passing image data. Killing infinite loops would be great

I've experimented with using it together with TensorFlow.js to avoid blocking the UI thread while performing computationally expensive operations. Operations do take a bit longer to complete in a web worker compared to the main thread, but in return you get a smooth UI and a better user experience

I actually like the way Web Workers can't touch the DOM. It's nice to finally give the DOM it's personal space for UI operations, which often leads to much more responsive apps especially at a large scale.

The pain points for me come in the form of shared dependencies. Large pieces of code that are accessible to multiple threads, and perhaps the UI thread, must get imported several times.

The lack of access to localStorage hurts in a lot places because any cache access must send data back and forth on the UI thread for operations that are probably entirely unrelated.

The lack of console.log makes debugging considerably worse. There are a couple of hacks to get around this but it's a bit crazy to pass messages between threads just to get a log printed.

Having to create a file per thread is very much a pain. Certain operations are tiny in terms of code and make more sense in the context of where you want to run theme. It'd be nice to run any function on a separate thread. Conceptually that would get weird because it would violate several properties of JavaScript closures. But it'd be nice to find some acceptable way of doing this sort of thing.

Web Workers are pretty good but can be unfriendly to developers at times.


I didn't know about web workers until now, would be a nice to try! I'm not sure though if they work well with ProcessingJS...

Webworkers lets JS be multi-threaded.

I used web workers extensively in a JS project a little over a year ago, and it was a nightmare. Granted what I was attempting was crazy, but it shouldn't have been as painful as it was.

Basically the "gotchas" are in the browser implementations. Each browser's web worker implementation is a little different, and those little differences (bugs) have huge implications in terms of what you can and can't do. For example: one browser may relay direct worker-to-worker messages via the main thread, so if your main thread is blocked your workers can't talk to each other, and that largely defeats the entire purpose of direct worker-to-worker communication.

Fortunately some of these issues have been fixed since (including that one, if memory serves), but it's slow going. I believe what happened was workers were introduced 5+ years ago, met with little interest initially, and the APIs have rotted for years until recently when interest picked up again, especially since SharedArrayBuffer.

My qualm with SharedArrayBuffer is that it kind of sucks to use in pure JS projects, because you have to serialize/deserialize everything to and from the buffer. With the Emscripten toolchain's pthreads support, as far as I'm aware you just compile your code and the heap lives inside SharedArrayBuffer. You don't have to write boilerplate serialization code, so compared to plain JavaScript it's seamless experience in that regard.

My advice to anyone using web workers in a pure JavaScript project is to use them as their name implies: offloading long-running calculations. If you try to treat them as true threads, you're going to have a bad time. Especially if your inter-worker messaging volume is high and you have frequent interdependent (blocking) calculations.

That said, the work I did was prior to SharedArrayBuffer. For very high-performance projects, it will likely be prudent to use SharedArrayBuffer itself as a messaging medium between workers.


This sounds great, but if all you're going is sending an AJAX request in the worker and stuffing the response into some element, I don't see much benefit. Most of the time you use an event handler to deal with the response so you're not blocking the main thread anyway. However, if there is any computation, DOM walking, or markup generation, I would definitely use a worker for that.

Unfortunately, this doesn't help the 60% of my users who really need it: the IE users with slow JS engines. I've measured 1-2 order of magnitude differences in performance between IE and Firefox/Chrome/Safari in my codebase, and there's just not much I can do for the IE users without withdrawing functionality I'm required to give them. (I wish Chrome Frame was an option, but I suspect that if they had the ability to use that, they'd have the ability to change browsers too, and they don't.)


WebWorkers have nothing to do with threading. They will not let you share memory, and this means that you waste time on seriazlizing/deserializing anything you pass to them, so from optimization point of view, they are more like processes. This makes js completely unsuitable for things that are data-heavy and cpu-bound (just cpu-bound may work, but it still not the best choice).

Web workers launched from the renderer work fairly well if you just need compute. I think I've also seen some apps add an additional BrowserWindow that's never displayed onscreen, although that will increase your memory overhead.

"I'm not sure how this addresses the resource load of Web Workers. What about their alternative makes it inherently lighter?"

The running of multiple tasklets within one WebWorker, from the sounds of it.

Given that there is a polyfill directory in the repo, and that nothing in what they've described immediately strikes me as needing any more browser support (give or take perhaps some quirky corner) for an initial implementation, it sounds like it's mostly stuff you could in theory write yourself. There's probably hundreds of similar things out there in the world already. But standardizing is often helpful, and there are ways the browser engine could theoretically accelerate these methods if they are explicitly supported with defined semantics the browser can understand. In particular, if the JIT can prove you are sending a "message" using this API that is a pure data object, it doesn't have to serialize that to a bytestream on one side and deserialize it on the other; it can just transfer the object via pointer passing. Or if it must still serialize/deserialize across a boundary, at least use a mechanism written in C++ that can be more efficient and easier than anything you can write in native JS.

(I say 'browser' above to leave open the possibility of DOM node proxying or whathaveyou; of course it would work in Node too.)

"At a minimum I would have thought that such a solution should enable a parallel form of map, filter, and reduce style operations. These are operations that are intrinsically designed for non-trivial tasks."

Surely these already exist somewhere? (If I know my JS library world, several dozen times over.) They should transfer over into the tasklet just fine.

Not sure this is worth it's own comment, so I'll just add that this strikes me as putting apartment-style threading into the browser: https://msdn.microsoft.com/en-us/library/ms809971.aspx based on a cooperative scheduling process, built on top of a dynamic scripting language. This would put the browser tech stack now somewhere in 2000-2001, I think. (This style of threading leans 1990s, but JS is better than any dynamic scripting language was in that timeframe, so I'll bump it forward a bit. But then back again for being cooperatively threaded.) It's getting there...

But in all seriousness, to the team looking at this, I would strongly suggest considering what this means in a world of WebAssembly, not just pure JS. Perhaps it all just works as-is, but it would still be nice to see some text about it.


That current situation is basically extremely powerful. It's effectively doing your own time slicing. In terms of code, to me, it's pretty.

IMHO it'd be far nicer just to speed js up and perhaps create some helper functionality to aid in splitting chunks of work up into bite size pieces, and make it more optimal.

It'd be much nicer to just have some yield statement which allows you to say "Hey, it's ok if you process any pending UI events, timers etc etc here". That way you could just have a single main loop with some yields in the right places. It'd create simpler, more maintainable code, and there's no reason it'd be slower or less responsive UI wise than the web worker version.

I can see the examples where web workers can be useful, where you're doing really CPU heavy backgroud work such as image processing etc. But I think people will end up using web workers for far more than that, which will make for some ugly code (IMHO).


Really, really wish you could do canvas manipulation with web workers. There's some experimental browser stuff, but nothing standard. I'd like to be able to do image manipulation with web workers.

The html5 web workers is the proposed long term solution: http://ejohn.org/blog/web-workers/

Writing GUI libraries (as the DOM is) which works with multithreaded code is hard, very hard, and often have awful performance.

So realistic solutions need to trade something: use co-operative multitasking or loose access to the DOM.

next

Legal | privacy