šŸ£ Three.js + WebAssembly

WebAssembly has a matured status 1.0 as of Monday, June 04, 2018: WebAssembly Specification ā€” WebAssembly 2.0 (Draft 2023-12-01)

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.

This discussion on Three.js + WebAssembly is not limited to functional programming rather let us discuss all findings related to Three.js + WebAssembly.

So curious to hear about what you have discovered and/or where you see Three.js + WebAssembly in the next 5 years!

3 Likes

What I donā€™t like about WebAssembly is the fact that your code base is split up into different languages. You can easily see this at the demo of the blog post. So you move away from a unilingual approach (just JavaScript) and start to develop with very technical, compiled programming languages like C/C++ or even Rust (a systems programming language). From my point of view, that makes web development more complicated.

I can understand when a whole software component like a physics engine is encapsulated as a WebAssembly module (especially since you have a better performance). But Iā€™m still not a fan of this architectureā€¦

3 Likes

Why do you draw a line at a whole physics engine, what makes this an atomic part in your view of the world? Why not an octree, or a raycaster, or an octree based raycaster?

1 Like

It was just an example.

Not worthy of a discussion? I think itā€™s a good example. There are lotā€™s of internals that most people donā€™t want to touch, but would prefer if they were as performant as it can get.

1 Like

As @Mugen87 responded with indeed was an example, wondering if others in the community of Three.js being used with WebAssembly in other ways? Apparently this isnā€™t happening as much as I had thought. Was only curious. Thanks for everyone(s) input so far!

1 Like

Iā€™m super curious about this topic but it is indeed intimidating, I tried to get started once and didnā€™t make much progress. I can definitely think of a use where more optimized code would help a lot.

1 Like

Did I read it wrong, or is it only a 1.0 draft?

I tried to use wasm a little a few months ago, but found the whole setup overly complex andā€“franklyā€“not worth the effort at the time (and at that time, not all browsers were shipping with support). Iā€™ve maintained a passing interest since then, but as of right now I donā€™t feel compelled to leave the pure JavaScript environment.

Why do you draw a line at a whole physics engineā€¦ why not an octree, or a raycaster, or an octree based raycaster?

For me thereā€™s a line because compiling, testing, and deploying WASM is currently a pain. Youā€™ll probably have to write bindings for every method you expose. Also, the compiled binary size tends to be much larger than the JS equivalent. For small simple modules, thatā€™s not (yet) worth it. Maybe that will change someday.

An example Iā€™m interested in is Recast/Detour, a navigation mesh and crowd pathfinding library commonly used in Unreal Engine and Unity. I spent a while trying to writing WASM bindings (see: embind) but gave up. There are existing attempts (like GitHub - vincent/recast.js: A wrapper for the RecastDetour navigation library for node and the browser) with Emscripten but they all seem unmaintained, buggy, and/or just arenā€™t set up the way I need.

3 Likes

Is this stuff that can improve as WASM matures, or is it an inherent flaw in the approach?

I think itā€™s just limitations in the current tooling, Iā€™m optimistic in the long run. There may always be a certain amount of size overhead on a WASM binary that would make it less practical for very small modules, but Iā€™m only guessing. :slight_smile:

I donā€™t know that itā€™s actually wasm's fault. This is just the next iteration of feature creep on the web.

Where this could become really powerful is if we dropped the idea of embedding this stuff into HTML, and wrote entire applications around wasm, with full browser support. If youā€™re going to write an app, make it as performant as possible via wasm. If youā€™re just creating documents, use HTML.

(An example of this is running APK files in Chrome. Only written in a web-native language instead.)

1 Like

Looks like the binary sizes have been improved in just the last few months, actually: Shrinking WebAssembly and JavaScript code sizes in Emscripten - Mozilla Hacks - the Web developer blog

My interest for now is access to some of the popular native libraries already used in gamedev. I have no interest in writing more native code myself. :slight_smile: But yeah, Google Earth is an example of a complete application where that could make sense ā€” currently it uses Chrome Native Client, but theyā€™ve said theyā€™re working toward using WASM instead.

1 Like

I think WebAssembly is a very interesting technology. Beside the runtime performance promise WebAssembly makes I want to highlight another cool feature.

Parsing and interpreting WebAssembly is much faster than with JavaScript and the parsed and compiled result can be stored into IndexedDB. We use WebAssembly in production and cache it into IndexedDB. This gave us a huge boost on app start up. The slowest thing in our app start up time is still the download and parsing of Three.js. Itā€™s not too bad but on low end devices you can really feel the pain of parsing and compiling JavaScript. So I think WebAssembly could be interesting. Furthermore it would be great if tree-shaking and deadcode elimination would work better with Three.js to get the file size down but thatā€™s another topic :wink:

FWIW, I wrote a post last year about my first experience with WebAssembly (https://blog.openbloc.fr/webassembly-first-steps/). From what I remember:

  • memory allocation wasnā€™t an easy task (has to be done at the init step, memory grow at runtime is expensive of course, malloc doesnā€™t work out of the box
  • if you have to pass data between JS and wasm at each render frame (I guess big arrays if weā€™re talking about three.js) I donā€™t know how efficient this runs
  • no DOM manipulation though there are projects like https://github.com/mbasso/asm-dom that aims at closing the gap.

WASM will be of great use for specific intensive taks which can be optimized this way, but it shouldnā€™t be expected as a replacement for JS, rather as for what i just mentioned and providing a interface for other languages, or alternative in the future.

Itā€™s already widely used for cryptominers, utilizing as much as possible out of your device :joy:

V8 is actually very powerful and will also compile to machine code where itā€™s possible. I will also mainly make use of it for processing tasks. JS can be heavily optimized too, iā€™ve seen libraries with rather bad practice making code unoptimizable, having exception code in a per-frame manner, allocating and dropping memory/objects frequently, or just an architecture which could be solved more efficiently. Some statements, invokations or allocations might seem small, but the entireness counts and how often things get invoked.

For THREE i would be already happy for now having finally offscreen canvas support in all browsers.

1 Like

I agree that a well built octree in webassembly, maybe even a gpu sided tree would be ideal.

The main limitation is how to handle having the data be shared across both js and wasm.

I havenā€™t done a whole lot with it, yet, but this has recently become a very interesting topic to me. Using something like Rust to implement really performance-bound operations like parsing, raycasting, or other math operations seems like a really good use case and with new tooling itā€™s gotten a whole lot easier to integrate web assembly with javascript. In Parcel, for example, itā€™s as easy as just including the .rs file:

import { add } from './add.rs'
console.log(add(2, 3))

There are also utilities that make it a lot easier to pass data between Javascript and Rust, as well.

thatā€™s super cool, i think! Iā€™m not sure I would personally go with Rust for all my WASM needs, but I can appreciate the attraction.

Thatā€™s some necroposting :smile_cat:

Iā€™ve recently ported a contouring algorithm based on octrees to WASM, and the performance gain was rather small, doesnā€™t mean WASM/the compiler will or has improved, iā€™ll definetly will put my hands on it again, but i donā€™t expect a too big difference.