from Hacker News

Snappy UIs with WebAssembly and Web Workers

by jaflo on 8/7/23, 2:45 PM with 63 comments

  • by afavour on 8/7/23, 3:46 PM

    I'm fascinated by WebAssembly and love that it exists but if anyone tells you they need to use WebAssembly to make the UI snappy I'd advise you interrogate that assertion thoroughly.

    I don't want to speak to this example too deeply because I don't know it (I see they're doing all sorts of stuff with audio so maybe they do need WebAssembly) but modern JavaScript VMs are very, very fast. 99% of webapps are absolutely fine using JavaScript.

    The far more important part of making snappy UIs is the Web Worker aspect. To my mind it's one of the key reasons native apps feel so much better than web ones: it's trivial to move an operation off the main thread, do an expensive calculation and then trivial to bring it back to the main thread again. Unfortuately the API for doing so on the web is extremely clunky, passing messages back and forth between a page context and a worker context. I'd recommend anyone thinking about this stuff to take a look at Comlink:

    https://www.npmjs.com/package/comlink

    it lets you wrap a lot of this complication up in simple promises, though you still have to think hard about what code lives inside a worker and what does not. In my ideal world all the code would live in the same place and we'd be freely exchanging stuff like you can in Swift. "Don't do it on the main thread" feels like a mantra taught to every new native developer as soon as it can be, the same discipline simply doesn't exist on the web. But neither do the required higher level language features/APIs.

  • by samwillis on 8/7/23, 4:30 PM

    WASM and Web Workers - unless carefully used - won't magically make your UI snappy.

    There are three reasons (for the vast majority of apps) that a UI feels sluggish:

    1. The network! Requesting data from a server is slow, by far the slowest aspect of any app. As a start, prefetch and cache, use a CDN, try edge platforms that move data and compute closer to the user. However, if you can explore Local First (http://localfirstweb.dev), for a web app it is the way we should be looking to build in future.

    2. They are doing work on the UI thread that takes longer than 16ms. This is where Web Workers are perfect, the DX around them isn't perfect, as another comment suggested Comlink helps, but there is a lot of opportunity here to build abstractions that help devs.

    3. Excessive animations that delay user interaction - there is so much bad UX where animations have been added that only make things slower. Good animations have a purpose, showing where something came from or is going, and never get in the way.

    Finally, we are well into diminishing returns with front end frameworks optimising the way they do templating and update the DOM. The key thing there now is DX, that is how you pick a framework, benchmarks are almost always useless.

  • by fenomas on 8/7/23, 4:49 PM

    Web Workers are a really great feature for performance. The way they want the worker code to live in a separate file makes them slightly annoying if you're using a bundler, but each bundler has a loader or similar feature for this, so all is mostly well.

    But the thing I haven't found a solution for is, the case where you want to use web workers inside a library that other people will be importing into their own project, and you don't know what bundler they'll use (or transpiler, minifier, etc). I can think of hairy ways to do it, that involve pre-building the worker JS and storing that text in your library, piping it into a file blob at runtime, or the like. But does anyone know a clean way of handling this?

  • by eole666 on 8/7/23, 3:46 PM

    Interesting article, but it's lacking a performance comparison between wasm and javascript running in workers.

    JS can be largely fast enough for a lot of use cases: if I had some WebAssembly to a project I need a good reason to do so.

  • by kevingadd on 8/7/23, 4:05 PM

    I would caution anyone looking to make their UI "snappy": while webassembly performance for things like raw compute - especially with simd - is superior, any time you need to interface with browser APIs like the DOM to update your UI you're now going to pay a bunch of interop costs that aren't present in native JavaScript. For some workloads this will make wasm meaningfully slower - especially ones that use strings.
  • by austin-cheney on 8/7/23, 5:18 PM

    > Running Fast(er) With WebAssembly

    How much faster?

    I have to ask because people frequently make claims about perform based upon unmeasured assumptions that are wrong more often than not. Worse than that, many of these imagined claims about performance tend to be off by one or more orders of magnitude.

  • by brundolf on 8/7/23, 5:15 PM

    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

  • by logankeenan on 8/7/23, 6:12 PM

    I have experimented with something similar by embedding an entire Rust Axum server in a service worker.

    I wrote a blog about it recently.

    https://logankeenan.com/posts/client-side-server-with-rust-a...

  • by amelius on 8/7/23, 9:44 PM

    Can we have structural sharing between web workers please? Because serializing everything as a message stream is not the most efficient way to go about many things. Also not the most programmer-friendly.
  • by mattlondon on 8/7/23, 5:29 PM

    > runs at speeds you would not be able to achieve with just JavaScript

    Is that true? Last I heard wasm was significantly slower than vanilla JavaScript in synthetic benchmarks.

    Has that changed recently?

  • by nwoli on 8/7/23, 4:51 PM

    With all this hype around full gpu UIs it rarely mentions the high latency around that. I’m much more excited about wasm making things snappier