Wasm unknown vs emscripten

In rust there re 2 wams targets:

  1. wasm32-unknown-unknown: WebAssembly
  2. wasm32-unknown-emscripten: WebAssembly via Emscripten

What are the differences between them, mainly in performance.

4 Likes

From what I understand the main difference is that wasm32-unknown-unknown creates a library to be used from Javascript, and wasm32-unknown-emscripten a full self-contained application.
I've never used the latter and I don't know if there are performance differences, I suspect that the underlying code generation is the same.

1 Like

IIUC wasm32-unknown-emscripten can be viewed as a legacy, "hacky" approach, so I think you should prefer using wasm32-unknown-unkown with wasm-bindgen or stdweb if possible.

1 Like

emscripten is best for cross compiling native apps, especially for its opengl to webgl support.

1 Like

Both targets compile to wasm, their difference is in how much they emulate a PC environment.

wasm32-unknown-emscripten

This target uses emscripten to provide the standard library. emscripten tries to provide things like TCP sockets/file io/multithreading/opengl so that you can compile your existing code to wasm and have it 'just work'. People compile their SDL2 applications, and emscripten will handle making DOM elements etc. that given you your gl canvas.

wasm32-unknown-unknown

This target is much more "bare bones". There is no attempt to emulate a PC - most system calls like IO will just panic (todo check this). However, the compiled wasm modules tend to be smaller since they don't need all that emulation, and we don't have to build and install an enormous C project. We do get an allocator (wee_alloc I believe) so we can use all our favorite heap allocated data structures (Vec, HashMap, ...). The awesome wasm-bindgen project provides interop with javascript, and then libraries like web-sys/js-sys provide rust functions that map to ECMAScript and Web API functions, so you can do anything like create HTML nodes.

I would recommend wasm32-unknown-unknown unless you are working with a legacy codebase, in which case you may need to use emscripten.

EDIT performance-wise - there shouldn't be much difference in theory, although that may not be true in practice. UX will definitely be better with wasm32-unknown-unknown since downloads are much smaller.

10 Likes

derekdreery's is a great explanation.

Just to clarify about the allocator, the default allocator for wasm32-unknown-unknown is dlmalloc. You can use wee_alloc instead, but you have to manually set it and right now it requires a nightly version of Rust.

3 Likes

FWIW, in one week wee_alloc will be usable on stable:

2 Likes