Hacker News new | ask | show | jobs
by zaksoup 1940 days ago
Something that I've been looking for as I try to learn more about WebAssembly is good examples of tasks that, when converted from Javascript to WebAssembly, would be good uses of WebAssembly for performance or memory or other reasons. Does anybody have a link to a blog post or good documentation like that?
11 comments

Determinism! [0] I'm switching a browser game side project from Typescript to WebAssembly because determinism enables a simpler style of multiplayer. Instead of relying on a server to manage state, I can just send inputs p2p like a modern fighting game (with rollback [1]). Then the game acts just like singleplayer! For a hobbyist like me, WebAssembly makes the minefield of multiplayer so much easier to navigate.

[0]: https://github.com/WebAssembly/design/blob/master/Nondetermi... [1] A blog post on rollback netcode (not in wasm): https://ki.infil.net/w02-netcode.html

What's nondeterministic about TypeScript / JavaScript?
Performance. See the graphs here: https://fitzgeraldnick.com/2018/02/26/speed-without-wizardry...

Look how much spread there is in the JS, and how little there is in the wasm.

Depending on what you're doing, this may or may not matter to you.

Object enumeration order (before ES2020 [1]), math function accuracy (Firefox and Chrome did standardize on fdlibm though [2]), various timings. All of them can be fixed with caution but it might be easier to use a platform where none of them matters (well, as long as you don't import Math.sin etc. from the environment...).

[1] https://stackoverflow.com/a/30919039/225272

[2] https://www.linux.com/training-tutorials/math-v8-broken-how-...

In many languages like those used to compile to WebAssembly (c++, c#, rust) enumerating standard dictionaries is non-deterministic. A javascript object is a dictionary, it is not surprising that it had an undefined order. If you need order use an array, if you need to lookup a value quickly use a dictionary, if you need both then you compose some ordered dictionary structure that internally has a dictionary and an array.

I guess since so many js devs never understood this and built code around one js engines property order behavior they had to go and specify it as a standard and now all js engine must add extra overhead to track and maintain property order...

Not sure how webassembly helps object enumeration order, it doesn't have objects to enumerate! To make objects you compile to webassembly from languages that most likely have undefined dictionary order and may not even have reflection to enumerate an object at runtime.

I agree that those issues are easy enough to avoid.

I think OP is saying that WebAsm allows for using languages that don't have these footguns. Perhaps there is some language they prefer to JS.

I’m using WASM as an execution environment for game code. It’s not so much for the performance aspect, it’s more that I can run the same simulations on the client and server side and have them agree. Rather than duplicating the simulation logic, say, in JavaScript and Rust, I can write the simulation logic once in Rust and use it in both places.
Figma: https://www.figma.com/

It's a design tool that runs entirely in your browser as a WebAssembly-based frontend tool (coded in C++ IIRC). Go kick the tires and play around with it--you will be amazed how fast, fluid and downright native the experience feels.

IMHO I think we're going to see more and more frontend experiences like this in the near future. For certain classes of complex apps we're starting to see the overhead of all the frontend JS cruft, polyfills, reactivity, etc. are just getting out of hand and destroying browsers on low-spec phones and machines. A little Go/C++/Rust/AssemblyScript, etc. app compiled to WebAssembly interacting with the DOM directly is incredibly fast and space efficient. The build system for something like Go or Rust is so much more sane and easy to use vs. a complex modern JS Webpack setup too.

edit: More details here: https://www.figma.com/blog/webassembly-cut-figmas-load-time-...

A few wasm projects I've worked on:

- An in-browser crossword puzzle generator: https://crossword.paulbutler.org/ (source: https://github.com/paulgb/crossword-composer)

- A multi-player word game: https://redwords.paulbutler.org/

- A library for synchronizing state between clients, used for that word game: https://aper.dev/ (source: https://github.com/aper-dev/aper very WIP right now)

In my experience, the single biggest perk of using WebAssembly is that I can use a language I'm very productive in (Rust) compared to JavaScript. Everything else is secondary. That said, I think these projects have specific advantages by virtue of being WebAssembly:

- The backtracking search used for the crossword puzzle generator is carefully implemented to reduce memory allocations. This would be tough to do in JavaScript, and I believe it's partly responsible for its performance.

- The word game uses a compression algorithm that benefits very noticeably from wasm-opt, to the point that I can't run it without it. Given that wasm-opt takes a non-trivial amount of time at compile time, I suspect the JavaScript JIT would be slow at doing something similar at runtime. This is just conjecture, I haven't checked.

- What Aper does just wouldn't be possible without Rust features like Serde and macros.

Chess websites compile their chess engines to WebAssembly so that they perform better in-browser.
I've experienced a 2x speedup when porting tight loops from JS to WASM. In my case, my tasks are decompression and texture decoding. I initially ported to C, and then ported to AssemblyScript, being careful to manually manage the memory along the way.

The old code was also very "tight-loop" code that's just math, and no GC allocation, so it's not applicable to many people here yet, and it's possible that JS interpreters have improved since when I ported (GC behavior has gotten quite noticeably better in V8 in the last two years), but I'll take the speedups I can get.

For comparison:

Old TypeScript: https://github.com/magcius/noclip.website/blob/master/src/Co...

New AssemblyScript: https://github.com/magcius/noclip.website/blob/master/src/as...

Wrapper for WebAssembly execution: https://github.com/magcius/noclip.website/blob/master/src/Co...

The YouTube series “HTTP 203” has a couple of great episodes on WebAssembly. Here’s one I like as it is both accessible and in depth: https://youtu.be/S0NQwttnr1I
That series deserves more views.
In Bucket Brigade (echo.jefftk.com), I'm currently encoding and decoding Opus audio with an emscripten port of the libopus. [1] This stresses the browser pretty hard, and at some point I'd love to switch to WebAssembly.

[1] https://github.com/jeffkaufman/bucket-brigade/blob/master/ht...

>. . .or other reasons.

In my case, that would be anything written in Python that targets WebAssembly.

If Javascript is obviated, that's one less programming language mouth to feed.

I personally use it to simplify and synchronize encryption logic between client side and server side; makes things a breeze especially if you don’t want to mess with Javascript’s crypto APIs.
Crypto miners were all the rage at some point.