9 ms·
The tug-of-war over server-side WebAssembly
- jitl 4y agoTo me it sounds like you could implement some parts of the WASI in JavaScript, so a WASM module depending on WASI doesn’t preclude it from running in the browser or a browser-like runtime. Instead of a bespoke shim generated by the compiler, you could use a standardized shim that provides a known subset of WASI. On the other hand relying on JS shims means a lot of guaranteed copying to/from the JS heap, which is a very annoying speed tax compared to… not. I wonder why browsers don’t allow direct WebIDL-based APIs direct from WASM to browser APIs
- paulgb 4y agoIndeed, some people are doing this: - WASI once had an official polyfill https://wasi.dev/polyfill/ https://wasi.dev/polyfill/, now apparently succeeded by https://github.com/bjorn3/browser_wasi_shim https://github.com/bjorn3/browser_wasi_shim - wasmer-js provides a JS polyfill for WASI https://docs.wasmer.io/integrations/js/wasi https://docs.wasmer.io/integrations/js/wasi - Cloudflare has a WIP polyfill https://github.com/cloudflare/workers-wasi https://github.com/cloudflare/workers-wasi I'm generally leery of non-temporary polyfills, so I'm not sure that any of these feel like a long-term viable option for me.
- jitl 4y ago> non-temporary polyfill Isn’t that what the compiler generated shim is that something like Emscripten emits? The Emscripten wrapper code is… frustrating.
- hardwaregeek 4y agoWasmer's one in theory works in the browser but I've yet to have it work. You have to polyfill some stuff like Buffer and even then you run into some annoying runtime Wasm errors.
- koch 4y agoI was investigating using wasm/wasi to implement a parser that is currently written in javascript, such that I would still be able to use it in the browser but also open up other avenues for it to be used on other platforms. I got bogged down in the wasi/wasm debate and terminology and different available runtimes (or whatever they should be called) - wasmtime, wasmer, wasmedge, fermyon, bytecode alliance... I probably would have spent more time and figured it out if I didn't want to learn rust right now. Seems rust is the best supported language for wasm as far as I can tell. Otherwise admittedly I would have used a large token context ChatGPT to convert the library to rust for me, and then also have it compile it to wasm.
- flohofwoe 4y agoJust wrap the core functionality into a 'pure' WASM module which doesn't need to access 'system APIs', and then if needed write two thin wrappers, one for the 'web personality' and one for the 'WASI personality'. WASI has the advantage that many compilers support it directly, e.g. in Zig: > cat hello.zig const print = @import("std").debug.print; pub fn main() void { print("Hello World!\n", .{}); } > zig build-exe hello.zig -target wasm32-wasi > wasmtime hello.wasm Hello World! Or if you prefer C: > cat hello.c #include <stdio.h> int main() { printf("Hello World!\n"); } > zig cc hello.c -o hello.wasm -target wasm32-wasi > wasmtime hello.wasm Hello World! (I guess Rust can do the same, or for a purely clang-based solution see: https://github.com/WebAssembly/wasi-sdk https://github.com/WebAssembly/wasi-sdk). ...while for web compatibility, you'll always need some sort of shim solution to talk to the Javascript APIs.
- antifa 4y agoThat was my experience. It was basically "use rust" or "nothing useful is implemented".
- samsquire 4y agoThis is a timely article for me since I've been trying to learn more about webassembly lately, thank you for it. I think the system interface is probably extremely important and significant part of webassembly and history. It's history making. It's the definition of a foundational interface that all users of webassembly shall inherit and need to target if it takes off. Which I hope it does. A standardised bytecode format is awesome! Why do I say this? The binary interface for C programming such as the amd64 SysV calling convention is established and is important for C FFI interoperability. Likewise, the syscall interface for Linux is established and so is Win32 API or POSIX. If people are trying to compile existing code so it doesn't need to be changed to support webassembly, then that's one constraint. Another constraint is performant Javascript interop. Another constraint which I personally find most interesting is the capability of defining a new API that is fit for purpose for application development. So that incorporates threading, garbage collection and sockets.
- eyberg 4y agoThe problem is that the wasm-on-the-server-side people don't seem to understand that the browser vendors will never ever let them have the laundry list of features that are necessary to fulfill Solomon's quoted tweet. The sooner the server-side people decide on their own standard (that won't be compatible 1:1 within the browser) for the server workloads the faster they can work on their end goals. WASI has been around for a while and is still missing quite a lot. raw sockets, dynamic linking, 32bit vs 64, linear memory (gc), memory protection, real threads, TLS - the list is seemingly endless. If I were building something in the wasm community (I'm not) I'd be less focused in on building one off bindings for fuctions-as-a-service, which seems to be the gtm right now and more focused on building the underlying foundations that are necessary.
- paulgb 4y agoI agree with your overall point, but interestingly it does look like Chrome is interested in shipping WASM GC in the browser. Here's their tracker for it: https://chromestatus.com/feature/6062715726462976 https://chromestatus.com/feature/6062715726462976
- rektide 4y agoGood discussion. There are still real tensions but I do tend to believe the component-model makes a huge amount of these questions moot. Quite comprehensive, but I think there's a pretty informative question to ask. If I write a Go wasm and you write a Rust wasm module, how do they work together? How can I call your thing? I could be mistaken on these but I think I one really does this now, and it's the macro-focus of component-model, to build a stable inter-module binary interface. Today... on the web there's not really a good solution other than hand writing more glue code in js to relay activity. On the server side wasi defines syscall like things you can call out & do, but I think it's just limited pre-baked operations, not a generic way to consumer a variety of external resources. Component-model is here to let us define exports & imports at a higher level & to let us stitch modules together via these interfaces. The article paints a very good very real story of how modules & runtimes interact, but that's a somewhat insufficient question, for the real goal of of interoperable modules working together. Asking how modules work with each other (not just the upper system) highlights how the systems question here is broader.
- imwithstoopid 4y ago> for the real goal of of interoperable modules working together CORBA, Beans etc predate the modern web but its telling that no one has really bothered to try to recreate them...what is the demand? server-side wasm just doesn't seem to be anything that is strongly needed and looks a lot like completists just scratching an itch two languages that only communicate at the wasm level...isn't this just a variation on "DLL Hell"? as to a Go program accessing a Rust module...on a practical level you would almost always be better off taking the thing in Rust that you want to use in Go and just doing a best-effort source translation or find some library out there that provides substitute functionality I'd rather have source translation tech that just gets functionality into the language I am using
- zdragnar 4y agoMaybe I'm missing the mark, but isn't server-side wasm basically solving the need for source translation? The semantics of golang and rust are so different that any translation runs the risk of producing wildly not-idiomatic code. Of course, you lose out on all the runtime benefits that various platforms might provide (I don't see anyone who is invested in the JVM giving it up for wasm) but why not have rust and golang binaries compiled to a common format and let the communicate directly? Personally, I don't do much polyglot programming these days so I don't really have a dog in the fight, so to speak, but my experience with source-to-source translation is that it tends to be pretty awful short of simple translations that keep the same runtime and underlying data primitives.
- RobotToaster 4y agoI'm confused, wouldn't server side webAssembly just be, well, assembly?
- hutzlibu 4y agoNo, as assembly is not the same as assembly, but dependant on the plattform. Webassembly is targeting a virtual cpu, so it is plattform independent.
- oneplane 4y agoWASI is also used as an ABI for ProxyWASM so you can load whatever custom code you want into a proxy to handle request transformations and the likes that are too large or bespoke to fit into plain configuration files. Envoy does this using a C++ host that starts V8, but there are legacy implementations without V8, and alpha implementations that did it with newer WASM runtimes.
- mike_hearn 4y agoThe other day I came across an interesting "alternative" to WASM which gives you OS portability using fully native code, without CPU portability, the latter seeming not that big of a deal these days anyway as cross compilers have got quite good and there are only two CPU archs in wide usage anyway. The idea is to simply run normal Linux binaries on macOS and Windows. How? You create a virtual machine using the Mac/Windows APIs without any OS inside, in fact without even any virtual hardware. It's literally just a new address space and some trivial min-viable VM configuration. Then you map the ELF binary and a ld.so into the VM with a minimal ELF interpreter, kick off execution and anytime there's a syscall you trap it and translate to the host OS syscalls. It can work quite well on macOS because the syscall interface is so similar. Note that this sort of VM is not: • A sandbox • A hardware abstraction Apps run this way hold all their data in the filing system of the host OS, they use the network stack of the host OS, etc. The VM is only being used to allow trapping and emulation of the syscall interface. The app isn't aware that it's being run in a special CPU mode on top of an emulated kernel. Advantages: lightweight, simple, apps can use all CPU features, can run at native speed, the Linux syscall interface is highly stable, based on POSIX specifications and you can easily pick a subset of it to standardize. Disadvantages: requires the emulator, apps exposed to missing features or quirks of the host OS e.g. Windows file system performance is much lower than Linux. WSL1 sort of worked that way, albeit without the VM aspect that lets userspace apps do it. They abandoned it partly for performance reasons and users expected all existing Linux apps to just work. But WASM doesn't target existing apps. It expects developers to bend and do things the WASM way, and accepts that not all apps are compatible with it, so that's not necessarily a problem. An example of how to implement this is NOAH: https://github.com/linux-noah/noah/ https://github.com/linux-noah/noah/
- mwcampbell 4y ago> without CPU portability, the latter seeming not that big of a deal these days anyway as cross compilers have got quite good and there are only two CPU archs in wide usage anyway Do we really want to surrender to the dominance of two proprietary ISAs? To me, the insistence on something like wasm bytecode is a kind of optimism, a hope that the current duopoly won't be permanent.
- hardwaregeek 4y agoI've been quite frustrated with the state of WebAssembly. It still feels like a platform that's in beta and not ready for production. Partially this is the slow pace of standardization, partially this is the lack of investment into tooling by various stakeholders. This plays out precisely as the blog post details with the split between WASI and Web Platform. Say you want to compile a Rust + C codebase to Wasm and run in the browser. You have three targets: wasm32-unknown-emscripten, wasm32-unknown-unknown, and wasm32-wasi. Emscripten is relatively old and not maintained. It'll work but you get some old JS that doesn't play well with newer stuff. wasm32-unknown-unknown has an ABI incompatibility which means you cannot interoperate between C compiled to Wasm and Rust compiled to Wasm. wasm32-wasi works, but now you have to have a WASI implementation in the browser and that's still very immature. Tools like wasm-bindgen or wasm-pack don't work with wasm32-wasi either. Basically you have the Web Platform backend (wasm32-unknown-unknown) that plays well with the browser part, but does not play well with the interoperability across languages part. And you have the WASI backend (wasm32-wasi) that plays well with the interoperability across languages part but does not play well with browser part.
- Arnavion 4y ago>wasm32-unknown-unknown has an ABI incompatibility which means you cannot interoperate between C compiled to Wasm and Rust compiled to Wasm. Since I was surprised to learn this, and to save everyone else the search, it's https://github.com/rust-lang/rust/issues/71871 https://github.com/rust-lang/rust/issues/71871
- justinclift 4y agoFurther down that GitHub issue, it mentions the problem has been fixed: * https://github.com/rust-lang/rust/issues/71871#issuecomment-757374318 https://github.com/rust-lang/rust/issues/71871#issuecomment-... * https://github.com/rust-lang/rust/pull/79998 https://github.com/rust-lang/rust/pull/79998 Weirdly though, there's another issue (opened prior) that's ongoing and seems to indicate things aren't fixed after all: * https://github.com/rustwasm/team/issues/291 https://github.com/rustwasm/team/issues/291
- vouwfietsman 4y agoShouldn't the allocation approach of WebAssembly change for this to be a real thing? Right now (at least in the browser) my main issue with WASM is that it just allocates a linear piece of memory that quickly fragments over time. How will this work for a server app?
- 0x457 4y agoThere really isn't an allocation approach in WASM. It just gives you a buffer and can grow, and the rest is up to you. Which means you have to bring your own allocator. Your fragmentation entirely depends on how good your allocator. Since we optimize for size on the web, it's hard to justify bringing the entire jemalloc into every wasm module.
- deathanatos 4y ago… the allocator can only do so much. If there's a small allocation after a large one, and the large on is freed and the small one held forever, you may never be able to de-fragment that. I think it's telling that Unix started with sbrk and ended up with mmap, here.
- flohofwoe 4y agoThe OS just gives you new chunks of memory, but it's the job of the application to manage the memory it has been given by the OS. Modern general purpose allocators are a bit more clever then just grabbing the next available address from a single free-list, usually they group allocations by size into buckets. Then there's specialized allocators (e.g. arena, bump, stack ...) which not only prevent fragmentation but also increase memory management performance. In general, memory fragmentation in a limited address space is only a problem for programs that don't have a proper memory management strategy.
- deathanatos 4y agoI'm aware of all of the things that you mention, and you can assume that the allocator I am discussing here is reasonably intelligent and does all of those things. Even with everything you mentioned, the point is that the allocator (doing all those things) cannot return free memory to the OS, because the APIs simply don't exist for it: that's what mmap() provides over sbrk(). In the worst case, even for an allocator doing all those things, this can result in an allocator being unable to return any memory: if exactly the last allocation remains alive, sbrk() cannot be called (as you'd free a still-live allocation); but in the case of mmap(), we can free most, or in the best case, all of the memory not in actual use.
- syrusakbary 4y agoI think the article summarizes well the issue but completely misses the point on why this is happening. First let me provide some context: I'm Syrus, CEO of Wasmer (a WebAssembly-powered company). There has been actors in the industry (I'm not naming them purposefully) that are using their corporate power (that is, their seats of influence over the standards committee) to move things forward as specifications even though their usage is minimal and not strong enough to yet become a standard. The issue about that strategy is that incentivizes creating new "standards" to gain control over them, even though there are already viable solutions for things that will solve people current needs. Let me put some examples of this: 1. Creating Wasi-NN instead of pushing for WebNN standard API [1] 2. Creating WebAssembly Interfaces instead of pushing for WebIDL (specially important for the browser, if we ever want to get DOM access from Wasm, this is probably the fastest way atm) 3. Creating WASI-fs instead of pushing towards the Filesystem spec [1] 4. And so on The issue is not on the technical advances per se, which I personally think they are great. But on the fact that those advancements start creating a breach that is different and competitive with the browser instead of being cohesive and complementary, and by doing that they are putting their governance power interests over the user needs. [1] https://www.w3.org/TR/webnn/ https://www.w3.org/TR/webnn/ [2] https://developer.mozilla.org/en-US/docs/Web/API/FileSystem https://developer.mozilla.org/en-US/docs/Web/API/FileSystem
- ctvo 4y agoDevil's advocate: Are these companies doing this to control the new standards or are they doing this because adhering to the web standard (both that you linked, I think?) puts them in a position where they'll be captive to an even larger committee (any web standards body), making it so any changes will take longer to push through, and implementation costs will be higher?
- kevingadd 4y agoArguably these are sort of the same thing. Being subject to the whims of the committees is a competitive disadvantage, since the committees are largely controlled by big corporate players. So if you create a new competing standard you control, it's 2-for-1: Not only are you no longer subject to the whims of big companies, but you get to set the rules. One of the upsides to using the big committee standards is that the big companies often have a reference implementation you can use, which is a time-saver. But then you can hit sharp edges or limitations.
- david2ndaccount 4y agoWasm in the browser is pretty cool, but I still don’t understand why you would want to give up the advantages of native code when running server side. Native code is faster and can actually use features of your hardware like the MMU, giving you things like virtual address space and memory protections. If you want to glue modules together, we can already do that - just expose symbols in your libraries and link them together.
- necessary 4y agoIf I understand the sandboxing capabilities correctly, it seems like it could be a neat way to run untrusted code from users.
- eyberg 4y agoThat's looking from the outside in but consider looking at it from the end-user (read: attacker's) viewpoint. The lack of memory protections that wasm currently has such as the lack of read-only memory or memory randomizations or anything else you really can't run any code with any level of assurance that it won't be taken advantage of. Typically a software engineer doesn't have to think about someone being able to rewrite a function during run-time or a statically defined variable because those memory protections are in place. It simply isn't allowed. However in wasm land, if you have a function that is say 'func isAdmin()' for instance you'd expect to return true if the logic is correct but without memory protections an attacker can force it to return true every time. This is one of the pretty serious features missing in wasm currently.
- int_19h 4y agowasm has separate address spaces for code and data, and wasm code does not even have read access to the code space, much less writing to it. The call stack is also completely isolated and not addressable. So how exactly would malicious code running in a wasm sandbox "rewrite a function"?
- deleted 4y ago
- aduitsis 4y agoDeep respect to the CloudABI folks, a project which inspired the WASI ideas: > CloudABI is no longer being maintained. It was an awesome experiment, but it never got enough traction to be sustainable. If you like the idea behind CloudABI, please consider looking into the WebAssembly System Interface (WASI). WASI's design has been inspired by CloudABI. https://github.com/NuxiNL/cloudlibc https://github.com/NuxiNL/cloudlibc edit: https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-overview.md https://github.com/bytecodealliance/wasmtime/blob/main/docs/... is a good reference and also mentions the Capsicum framework (https://www.cl.cam.ac.uk/research/security/capsicum/ https://www.cl.cam.ac.uk/research/security/capsicum/). Which is present in FreeBSD for several versions btw.
- frithsun 4y agoThe fight for WASI is dramatically more important for the future of tech than AI, bitcoin, and all the other silly fads. If WASM gets sucked into the vortex of pragmatism and fails at its original mission of discarding all of the technical debt and obsolete paradigms, then we'll miss out on a golden opportunity to reinvent the modern technology stack. Those who want to deliver something that works right now can fork the project and call it WARN (WebAssemblyish Right Now).
- Havoc 4y agoImportant yes but not sure it matters which way it goes. Looking at how things went with JS this stuff evolves over time anyway as new needs come up
- efitz 4y agos/1990s/2020s/g s/Java/WebAssembly/g There! All up-to-date!
- thrown123098 4y ago[dead]
- int_19h 4y agoJava bytecode was (and still is) fairly strongly tailored to Java. Which means that, on one hand, it deals with abstractions like classes and object references, and on the other hand, there's no way to, say, just read or write some memory address. wasm is much lower level bytecode that e.g. C can be compiled to.
- panick21_ 4y agoMan people have to get over this joke. Its been like 10 years of every time WebAssembly comes up somebody has to make this 'joke'. Like it was never funny, and it was always fucking dumb. Java isn't the first language base on bytecode, and WebAssembly will not be the last.
- pjmlp 4y agoIt is only happening, because now we have startups with VC, trying to redo Java and .NET application servers, but now with Kubernetes and WASM containers they are supposed to be hip and trendy with plenty of YAML, not like the granddaddy's JVM and CLR based boring servers with XML all over place.
- panic 4y agoThere’s a third path here, which is to target WebAssembly directly, with no wrappers. Then you can import just the functionality the module needs to work. The benefit is that you can actually understand what your code is capable of doing to its environment (instead of working with the “one size fits all” type of interface that has produced so many security issues on existing platforms).
- Animats 4y agoThe amount of effort that goes into packaging continues to amaze me. Nested packaging, even, like a Matryoshka doll. Also, how this ecosystem replicates the era of Java in both browser and server.
- eliben 4y agoVery timely post. I was recently looking at the ways one can implement a plugin system using WASM (outside the browser). Communicating between the host application and the plugin is sure tricky... I've seen places that use WASI to map stdin/stdout to files and use that. It feels... wrong.