Is WebAssembly magic performance pixie dust? (2021)
surma.dev
surma.dev
1) Is it too early to adopt WASM for production use in a small company with limited resources?
2) If we did decide to go all in on WASM, what sort of gotchas might we be dealing with?
Thanks everyone!
It really depends on what you are doing with it.
For things like "I've got this C lib that I want to be able to call from the web" it's probably fine. For things like "I want to write my whole webpage in wasm" it's not ready for that (and, frankly, likely never will be).
It's a matter of finding the right fit.
> If we did decide to go all in on WASM, what sort of gotchas might we be dealing with?
Depends on what you mean by "all in" if you mean, "I want ALL my webapp logic to live in wasm" then the biggest gotcha you'll face is shipping stuff into and out of the VM (including DOM elements) is really painful. IMO, UX continues to best be done with Javascript or compile to javascript langauges (typescript, for example). Using a language like C, C++, or Rust to do UX work will simply not be pleasant, will be hard to hire for, and will complicate a lot of your build system.
Now, if by all in you mean "This logic only lives in this library and we are shipping that out as a WASM module" then I think wasm will work well there. Better, in fact, than other options like kotlin to native or J2CL (IMO).
That said, there are fledgling UX frameworks written entirely for WASM. However, they are all relatively young and AFAIK, not exactly well established.
This becomes an engineering decision and balancing act that I don't think can be 100% answered for your company.
I don't expect any of the UI work will ever be done in WASM (because it doesn't need to be shared with the embedded side of things). It is more porting standalone libraries that would be useful for both like file parsing and networking libraries. (In particular, the library I ported was a file parser).
WASM works best in cases of strict CPU and limited GPU processing (through webgl).
What already exists is multiple bridge libraries to make porting stuff from JS -> WASM and back again easier.
For example: https://rustwasm.github.io/wasm-bindgen/examples/dom.html
[0]: https://github.com/WebAssembly/gc/blob/main/proposals/gc/Ove...
It is a good way to get memory leaks, but a lot of websites already have those.
The big gotcha used to be debugging but Chrome dev tools actually has DWARF support now. Of course as an embedded developer you're probably already used to poor debugging support.
[1] https://james.darpinian.com/blog/integer-math-in-javascript
A wasm b-tree, skip list, rope, etc seems to outperform the equivalent javascript code by many times.
Edit: I just whipped up a real benchmark to test this, replaying some text editing traces[1].
Replaying the automerge-perf editing trace in javascript naively takes 610ms. Using a javascript based skip list it takes 77ms[2]. In native rust, with a rust port of the same skip list code I can process the same editing trace in 6ms[3]. Or 20ms when that rust code is compiled to wasm.
So in this case, we're seeing about a 4x performance improvement using wasm, or 13x performance improvement using native code.
[1] https://github.com/josephg/crdt-benchmarks
[2] This code https://gist.github.com/josephg/bcb2e74e52dc9c4651249fdffc48... using this library: https://www.npmjs.com/package/jumprope
The most performance-critical section is the "arbiter applyImpulse" physics code[2], which is all math.
I tried putting everything in as big TypedArray to avoid all the object lookups, but performance got slightly worse, not better. I still have no idea why. I think the reason is that the optimizer couldn't optimize the typedarray lookups at the time. Not in the same way it can optimize math on normal objects.
Maybe v8 is more clever now? I dunno!
The biggest performance win I got was from inlining vector fields. Chipmunk heavily uses {x,y} 2d vectors. Lots of objects looked like this: {pos: {x, y}, velocity: {x, y}, ...}. Flattening everything to this {posx, posy, velocityx, velocityy, ...} made the code uglier. But it caused a massive performance improvement because it reduced the number of objects allocated on the heap. (This one change reduced the number of heap allocations by about 70% from memory, and it caused a double-digit performance improvement overall.)
As I see it, Javascript will always be much slower than other languages for complex data structures because everything is stored on the heap.
[1] https://github.com/josephg/chipmunk-js
[2] https://github.com/josephg/Chipmunk-js/blob/ec447072458f4009...
I suspects if I re-ran that test, performance would have improved across the board but I'd get the same relative performance result with TypedArray code.
It would be fascinating to try though. I wish I kept the code.
> [1] Add | 0 after every math operation to get a 32-bit signed integer result, and >>> 0 for a 32-bit unsigned integer result.
That's definitely gonna cause a few "wtf?" moments for everyone else on your team, lol
Source? Every benchmark I've seen that has JS comparable / faster than C uses an extremely suboptimal C implementation.
To see results, show "vanillajs-1" and "wasm-bindgen", then hide everything else. WASM is about 6% slower, 18% longer startup, and 66% more memory usage.
Note this is a UI benchmark so the results are overwhelmingly dominated by DOM interop. Things should improve if the WASM interface types proposal ever lands.
I think the electron memory usage comes down to the massive HTML spec and bloated old browser codebases. It's not JS. Node+V8 doesn't have nearly the memory usage of Chrome+V8.
Browsers are often able to defer parsing of JS functions until they're called, so dead JS code doesn't cost much in parsing time.
In JS first run goes through an interpreter (without a delay for compilation/optimization), so JS has a pretty low latency for initial execution.
JS is relatively easy to split into pieces and lazy load (there are various bundlers that support "chunking"), and not loading code is faster than fastest parsers. WASM could theoretically do that too, but current languages and tooling are more geared towards monolithic executables. For UI, where time to interactive matters most, JS will likely do a better than a big blob of WASM.
WASM still needs to call out to JS for DOM interactions, so if your UI is DOM-based, you'll need a bunch of JS anyway, and have JS<>WASM communication overhead.
You sure? Just figuring out what to call us going to typically require full parsing to find identifiers, scoping, etc.
I'm all in on Wasm on the medium-to-long term as I think it will eventually dominate everything (embedded, mobile and web). The comparison with JS is a bit unfair as the former has had a 20+ year head start plus billions of dollars (yes, billions) in R&D to make it as performant as possible.
I think JS is a great language/platform and I consider V8 an amazing piece of engineering, it would be on my list for the seven wonders of the digital world. Wasm will get there someday and will take the place of JS, IMO.
Yes, but there's also a reason why the Rust -> JS route never took off.
Wasm is positioning itself as the common runtime for a lot of frontends (term borrowed from LLVM). You could see it as some sort of spiritual successor to the JVM, and it may actually accomplish the goal of "Write once, run anywhere" to a much greater extent.
(Btw, I am not criticizing Java here, I've worked with it and the JVM and other derivative languages for almost a decade and they all are quite valuable tools!)
What is this reason?
Do you also think it will displace runtimes on the server? I'm thinking about the JVM and CLR.
Btw, I think the GraalVM project is another amazing piece of tech with a bright future.
Even if they want to, the programs have to be approved by Master Control. Apple [1] and Microsoft [2] are gradually tightening the restrictions for installing an executable on their platform. Downloading a program and installing it is now called "sideloading". Even for desktops.
[1] https://developer.apple.com/app-store/review/guidelines/
[2] https://docs.microsoft.com/en-us/windows/uwp/publish/store-p...
I have about 20 exe in a folder that say you're wrong. I also have about 9 other folders with unzipped programs that say you're wrong. Nothing is stopping anyone from downloading an executable file and running it on a desktop computer. Nor should it.
How do you think people do software development? Or do you just think new programs come from magic pixie dust?
It's possible, for now, to turn off Windows S mode. For now. Usually. The Windows Store server has to approve turning it off. In an enterprise configuration, some in-house server has to approve.
[1] https://support.microsoft.com/en-us/windows/windows-10-and-w...
As much as I enjoy seeing someone trash Microsoft, this is just a dumb take. Like I said to the other user, how do you think software development happens? Microsoft wants people to develop using Windows [1][2][3]. You can only do that by installing additional software. This is not, and never will go away. Yes, some corporate setting will have locked down computers, but thats how its already been for several decades.
1. https://wikipedia.org/wiki/.NET
2. https://wikipedia.org/wiki/C_Sharp_(programming_language)
3. https://wikipedia.org/wiki/F_Sharp_(programming_language)
OK then, ask the admin to install it, I don't see the problem. If its appropriate work software, then it shouldn't be an issue. Web browser should be for... browsing the web. If you're simply using a browser to bypass admin restrictions, it seems like you're doing something wrong.
This takes weeks and can often take months. If the choice is between writing the business case, getting management sign off and waiting weeks for deployment vs running it immediately in the browser, I'm choosing the browser.
Can we just run Docker containers in the browser and be done with it?
Also even if you don't care about performance, WASM can arguably provide a sizable security benefit for a number of use cases such as not-fully trusted plugins.
The article was also posted in HN about a year ago: https://news.ycombinator.com/item?id=26803155
Gaming and other graphic intensive or computationally expensive apps are probably the best use case.
I haven't had the time to read more, but I'd be curious to learn why they didn't just target full TypeScript compatibility. That would reduce the barrier to entry materially.
They say: "... the language is intentionally mirroring the behaviors and semantics of TypeScript (and therefore JavaScript) "
And then: "... which means that the act of “porting” TypeScript to AssemblyScript are often mostly cosmetic, usually just adding type annotations."
But it’s fucking fast, faster than anyone (including me) would have believed a few years ago.
The ability to live-update software before the native code can arrive is a game-changer.
This stuff is a big deal.
i was wondering about the use case, from what little i've read, assemblyscript is an alternative for devs who want to stick to typescript style language with some fine grained control for lower level webassembly. see some utility for niche cases where perfor mance is needed for complex data structures, not entirely convinced though, specially with v8 JS giving excellent performace out of the box
I could be wrong, but that's my going by 60 mph, looking out the window view