When Is WebAssembly Going to Get DOM Support?
queue.acm.org183 points by jazzypants 3 days ago
183 points by jazzypants 3 days ago
We use WASM quite a bit for embedding a ton of Rust code with very company specific domain code into our web frontend. Pretty cool, because now your backend and frontend can share all kinds of logic without endless network calls.
But it’s safe to say that the interaction layer between the two is extremely painful. We have nicely modeled type-safe code in both the Rust and TypeScript world and an extremely janky layer in between. You need a lot of inherently slow and unsafe glue code to make anything work. Part is WASM related, part of it wasm-bindgen. What were they thinking?
I’ve read that WASM isn’t designed with this purpose in mind to go back and forth over the boundary often. That it fits the purpose more of heaving longer running compute in the background and bring over some chunk of data in the end. Why create a generic bytecode execution platform and limit the use case so much? Not everyone is building an in-browser crypto miner.
The whole WASM story is confusing to me.
My reading of it is that the people furthering WASM aren't really associated with just browsers anymore and they are building a whole new VM ecosystem that the browser people aren't interested in. This is just my take since I am not internal to those organizations. But you have the whole web assembly component model and browsers just do not seem interested in picking that up at all.
So on the one side you have organizations that definitely don't want to easily give network/filesystem/etc. access to code and on the other side you have people wanting it to be easier to get this access. The browser is the main driving force for WASM, as I see it, because outside of the browser the need for sandboxing is limited to plugins (where LUA often gets used) since otherwise you can run a binary or a docker container. So WASM doesn't really have much impetus to improve beyond compute.
> So on the one side you have organizations that definitely don't want to easily give network/filesystem/etc. access to code and on the other side you have people wanting it to be easier to get this access
I don't think this is entirely fair or accurate. This isn't how Wasm runtimes work. Making it possible for the sandbox to explicitly request specific resource access is not quite the same thing as what you're implying here.
> The browser is the main driving force for WASM, as I see it
This hasn't been the case for a while. In your first paragraph you yourself say that 'the people furthering WASM are [...] building a whole new VM ecosystem that the browser people aren't interested in' - if that's the case, how can the browser be the main driving force for Wasm? It's true, though, that there's verey little revenue in browser-based Wasm. There is revenue in enterprise compute.
> because outside of the browser the need for sandboxing is limited to plugins (where LUA often gets used) since otherwise you can run a binary or a docker container
Not exactly true when you consider that docker containers are orders of magnitude bigger, slower to mirror and start up, require architecture specific binaries, are not great at actually 'containing' fallout from insecure code, supply chain vulns, etc.. The potential benefits to enterprise orgs that ship thousands of multi-gig docker containers a week with microservices architectures that just run simple business logic, are very substantial. They just rarely make it to the hn frontpage, because they really are boring.
However, the Wasm push in enterprise compute is real, and the value is real. But you're right that the ecosystem and its sponsorship is still struggling - in some part due to lack of support for the component model by the browser people. The component model support introduced in go 1.25 has been huge though, at least for the (imho bigger) enterprise compute use case, and the upcoming update to the component model (wasi p3) should make a ton of this stuff way more usable. So it's a really interesting time for Wasm.
> The potential benefits to enterprise orgs that ship thousands of multi-gig docker containers a week with microservices architectures that just run simple business logic, are very substantial.
What are you talking about? Alpine container image is <5MB. Debian container image (if you really need glibc) is 30MB. wasmtime is 50MB.
If a service has a multi-gig container, that is for other stuff than the Docker overhead itself, so would also be a multi-gig app for WASM too.
Also, Docker images get overlayed. So if I have many Go or Rust apps running on Alpine or Debian as simple static binaries, the 5MB/30MB base system only exists once. (Same as a wasmtime binary running multiple programs).
> Alpine container image is <5MB. Debian container image (if you really need glibc) is 30MB. wasmtime is 50MB.
That's not the deployment model of wasm. You don't ship the runtime and the code in a container.
If you look at crun, it can detect if your container is wasm and run it automatically, without your container bundling the runtime. I don't know what crun does, but in wasmcloud for example, you're running multiple different wasm applications atop the same wam runtime. https://github.com/containers/crun/blob/main/docs/wasm-wasi-...
My point is that that's exactly the deployment model of Docker. So if I have 20 apps that are a Go binary + config on top of Alpine, that Alpine layer will only exist once and be shared by all the containers.
If I have 20 apps that depend on a 300MB bundle of C++ libraries + ~10MB for each app, as long as the versions are the same, and I am halfway competent at writing containers, the storage usage won't be 20 * 310MB, but 300MB + 20 * 10MB.
Of course in practice each of the 20 different C++ apps will depend on a lot of random mutually exclusive stuff leading to huge sizes. But there's rarely any reason for 20 Go (or Rust) apps to base their containers on anything other than lean Alpine or Debian containers.
Even for deploying wasm containers. Maybe there are certain technical reasons why they needed an alternate "container" runtime (wasi) to run wasm workloads with CRI orchestration, but size is not a legitimate reason. If you made a standard container image with the wasm runtime and all wasm applications simply base off that image and add the code, the wasm runtime will be shared between them, and only the code will be unique.
"Ah, but each container will run it's own separate runtime process." Sure, but the most valuable resource that probably wastes is a PID (and however many TIDs). Processes exec'ing the same program will share a .text and .rodata sections and the .data and .bss segments are COW'ed.
Assuming the memory usage of the wasm runtime (.data and .bss modifications + stack and heap usage) is vaguely k + sum(p_i) where p_i is some value associated with process i, then running a single runtime instead of running n runtimes saves (n - 1) * k memory. The question then becomes how much is k. If k is small (a couple megs), then there really isn't any significant advantage to it, unless you're running an order of magnitude more wasm processes than you would traditional containers. Or, in other words if p_i is typically small. Or, in other other words, if p_i/k is small.
If p_i/k is large (if your programs have a significant size), wasi provides no significant size advantage, on disk or in memory, over just running the wasm runtime in a traditional container. Maybe there are other advantages, but size isn't one of them.
> "Ah, but each container will run it's own separate runtime process." Sure, but the most valuable resource that probably wastes is a PID (and however many TIDs). Processes exec'ing the same program will share a .text and .rodata sections and the .data and .bss segments are COW'ed.
In terms of memory footprint, I can allow that the OS may be smart enough to share a lot of the exec'ed process if it's run multiple times. With Go and Rust and other statically compiled programs, that's going to scale to the number of instances of a service. With Node you might scale more, but then you need to start dynamically loading app code and that won't be shared.
With wasm hosts, you can just ship your app code, and ask the wasm host to provide libraries to you. So you can have vastly more memory sharing. Wasm allows a lot of what you term p_i to be shifted into k through this sharing.
But there's so many other reasons to have a a shared runtime rather than many processes.
Context switching can be a huge cost, one that a wasm host can potentially avoid as it switches across different app workloads. Folks see similar wins from v8 isolates, which for example CloudFlare has used on their worker platform to allow them to scale up to a massive number of ultra-light worker.
> Even for deploying wasm containers. Maybe there are certain technical reasons why they needed an alternate "container" runtime (wasi) to run wasm workloads with CRI orchestration, but size is not a legitimate reason. If you made a standard container image with the wasm runtime and all wasm applications simply base off that image and add the code, the wasm runtime will be shared between them, and only the code will be unique
The above talks to some of the technical reasons why an alternate runtime enables such leaps and bounds versus the container world. Memory size is absolutely the core reason; that you can fit lots of tiny micro-processes on a wasm host, and have them all sharing the same set of libraries. Disk size is a win for the same reason, that containers don't need to bundle their dependencies, just ask for them. There's a 2022 post talking about containers, isolates, and wasm, talking more to all this arch: https://notes.crmarsh.com/isolates-microvms-and-webassembly
If you want small function-style services then yea, that's valid, because p_i is really small.
The question is really if you want hundreds of big and medium-sized services on a server, or tens of thousands of tiny services. This is a design question. And while my personal preference would be for the former, probably because that's what I'm used to, I'll admit there could be certain advantages to the latter.
Good job, you've convinced me this can be valid.
These numbers are true, but you'd be amazed and the number of organisations that have containers that are just based on ubuntu:latest, and don't strip package cache etc.
ubuntu:latest is also 30MB, like Debian.
Obviously an unoptimized C++/Python stack that depends on a billion .so's (specific versions only) and pip packages is going to waste space. The advantage of containers for these apps is that it can "contain" the problem, without having to rewrite them.
The "modern" languages: Go and Rust produce apps that depend either only on glibc (Rust) or on nothing at all (Rust w/ musl and Go). You can plop these binaries on any Linux system and they will "just work" (provided the kernel isn't ancient). Sure, the binaries can be fat, but it's a few dozen megabytes at the worst. This is not an issue as long as you architect around it (prefer busybox-style everything-in-a-binary to coreutils-style many-binaries).
Moreover, a VM isn't much necessary, as these programming languages can be easily cross-compiled (especially Go, for which I have the most experience). Compared to C/C++ where cross-compiling is a massive pain which led to Java and it's VM dominating because it made cross-compilation unnecessary, I can run `GOOS=windows GOARCH=arm64 go build` and build a native windows arm64 binary from x86-64 Linux with nothing but the standard Go compiler.
The advantage of containers for Rust and Go lies in orchestration and separation of filesystem, user, ipc etc. namespaces. Especially orchestration in a distributed (cluster) environment. These containers need nothing more than the Alpine environment, configs, static data and the binary to run.
I fail to see what problem WASM is trying to solve in this space.
You know what would be cool? A built in way for your browser to automatically download and run local-first software as a docker container, in the background without user confirmation.
The problem with that idea is docker isn’t as secure as wasm is. That’s one big difference: wasm is designed for security in ways that docker is not.
The other big difference is that wasm is in-process, which theoretically should reduce overhead of switching between multiple separate running softwares.
That wouldn't be cross-platform. Browsers couldn't even ship SQL because it would inevitably tie them to sqlite, specifically, forever. They definitely can't ship something that requires a whole Linux kernel.
> Browsers couldn't even ship SQL because it would inevitably tie them to sqlite, specifically, forever.
Nonsense.
Chrome store their sqlite db in C:\Users\%USERNAME%\AppData\Local\Google\Chrome\User Data\Default\databases
And Firefox:
> Why Firefox Uses SQLite
> Cross-Platform Compatibility: Works seamlessly across all platforms Firefox supports.
https://www.w3resource.com/sqlite/snippets/firefox-sqlite-gu...