Hacker News new | ask | show | jobs
by olsonjeffery 756 days ago
It's hard because, a lot of this stuff (async WASM, effect-driven WASM, GC in WASM, etc) is all driven by the desire to push these concerns out of wasm bytecodes, because it explodes the binary's size.

I have a pretty trivial webapp written in Yew and I stopped working on it once I saw that the wasm artifacts were weighing at 4MB (uncompressed) for relatively little functionality. THIS is what is driving the next round of "work" on WASM: to wring more functionality out of a system (WASI 0.1) designed as a drop-in replacement for emscripten output. As an aside on this point, the author is waaaay in front of their skies with basically all of their critiques around ByteCode Alliance; A lot of innuendo to basically serve a rhetorical point that isn't really true (WASI 0.1 is "good enough"). It has drawbacks! That's what the iterations on the protocol are exploring!

And this tech is cool and all, but right now a reasonably-vanilla typescript react app w/ a modern bundler (ie including stuff like router, redux, oidc, etc) is beating the breaks off of a similar app in Rust or C#/Blazor in terms of bin size. And there's no perf or API-surface argument that overcomes this. And it has chilling effect on developers when they reach for this tech.

2 comments

Then maybe "this stuff" should not have been tacked onto the WASM standard in the first place? There's no free lunch. Sure, it sucks that your favorite garbage-collected interpreter/runtime bloats your module size. But the alternative option is to bloat every WASM engine by shoehorning your use case into the standard.
As much as binary size should be a problem for individual developers to deal with, I've seen how those individual developers treat Electron. There's no doubt in my mind that someone will ship 50 little JavaScript programs inside wasm modules, each with its own garbage collector. Then it becomes my problem.

Promise you won't tell the GC'd language enthusiasts this, but wasm engines supporting the wasm-gc proposal don't need to ever run a garbage collector. A simple bump allocator is 100% compliant, as long as the module's memory gets cleaned up once it terminates. Wasm engines for embedded systems will probably do exactly that, and leak memory rather than collect garbage. The web already has a garbage collector for JS, so not a big deal there either. Bloat has its cost, but at least it's only paid by cloud/edge/desktop and other use-cases that can afford to put it in their engine.

I think wasm-gc is worth it for WebAssembly. The dream is "run any language, anywhere" but it's always been easier for low level languages like C, C++ and Rust, because their binaries are smaller. Maybe with things like wasm-gc, WebAssembly can be great for C, C++, Rust, but also JavaScript and Python, Java and Go, OCaml, Perl, and whatever language gets sprung on us next.

It really depends on what you're using. If you use Rust with `wasm32-unknown-unknown`, you'll likely get small binaries (<200 kB). If you use C++ and Emscripten with all features enabled, then yeah you'll have multiple megabytes with all the libcxx and musl stuff.
My direct experience with wasm32-unknown-uknown contradicts your own. I am building a yew on nightly, moving between release or debug affects nothing.
> moving between release or debug affects nothing

I'd start with that, it's an obvious red flag. Switching between both should create huge differences. Also look into `wasm-opt` from the Binaryen project for post-link optimizations, `wasm-ld` from LLVM isn't that great at DCE.

Thanks for the feedback.

I was wrong about debug vs release; It's the difference between 4.0MB & 893KB on a ~500 LOC rust codebase (per cloc).

I want to observe that your suggestions don't undermine or refute my point about problems that WASM adoption faces. This serves to underline that the developer experience needs work. Opinions may differ on how much. Also that "developer experience" runs on multiple axes of concern (bin size, perf, accessibility, utility of language, etc).

I agree, my personal take: if you don't want to get your hands dirty, WebAssembly is not ready for you yet. It'll take at least 5 more years before the tooling gets into a state where things should just work (especially DWARF support). I mean, we still cannot free memory! (actually there is a crazy way by recreating a new WebAssembly instance with a shrunk'd `ArrayBuffer`, but it requires you writing your own memory allocator)

My point is: if you're comfortable working with a slightly obscure microcontroller, then you won't have much problems. LLVM supports WebAssembly out of the box, so it mostly feels like programming for one of those.

Anecdotally: we run a large Rust app in under 1 MB of WebAssembly at Zscaler.

> 4.0MB & 893KB on a ~500 LOC rust codebase (per cloc).

My guess is 50,000 LOC would not be 100 times bigger err

Methinks you are counting overhead

More accurately... meguess