Why WebAssembly Will Disrupt the Operating System
It’s fair to say that the core paradigms of the operating systems on which our systems run haven’t really changed since the 1970s, even though we’ve learned a lot in the intervening time.
We’ve seen innovation, particularly in terms of UX and concurrency. But, according to Liam Crilly, senior director of product management at NGINX (part of F5), it feels like we are still just optimizing for the local maximum.
“We’ve got threads and we’ve got processes, but they’re all rooted in the same abstraction,” he told the New Stack.
Crilly believes that WebAssembly (Wasm) affords software developers a rare opportunity to rethink the entire way operating systems work, and that we would be wise to take advantage of this.
“With WebAssembly,” he said, “we kind of get to start again.”
Wasm and the Diffusion of Innovation
We’ve covered WebAssembly in detail on The New Stack before, but if you aren’t familiar with it some more background may prove useful. WebAssembly is a binary instruction format for a very small, stack-based virtual machine — in effect, a very naive computer.
Because it is stack-based, the code that runs on it is simple and can be highly optimized, making it extremely fast. The bytecode that targets it is portable, and Wasm binary files are extremely small. They are also secure, unable to do anything unless the host runtime lets them. You can write code destined to run in Wasm using a wide variety of high-level languages, including C/ C++, C#, Dart, Go, Kotlin, Rust and Swift.
Moreover, the qualities that make Wasm attractive as a browser technology — it’s efficient, fast and safe — have seen it used in a wide variety of other contexts. These include Cloudflare Workers, Envoy extensions, Fastly’s Compute@Edge, and recently, NGINX Unit. Kevin Hoffman, an author, technologist and Wasm enthusiast, has gone as far as to argue that the cloud is where Wasm really shines.
Inevitably though, as adoption of the technology has grown and broadened, there is some tension in terms of how far one should extend the capabilities of the Wasm virtual machine. Within the community, an ongoing conversation explores what the future of the technology should look like and, more generally, how much it should resemble the way computer systems work.
Underlying this tension there is, as always in software, a set of trade-offs. When you think about the diffusion of innovation within the technology industry, it is usually true that things that appear familiar get adopted more rapidly.
If you think of Java, say, one of the reasons it took off so quickly was that it looked enough like C++ that people used to the C family of languages could pick it up quickly. It was “C++ without the guns, knives or clubs,” as its lead designer, James Gosling, memorably put it.
This was intentional; during his keynote at reClojure last year, Gosling said, “I wanted C programmers to be able to look at a Java program and think they understood what was going on. And mostly they did.”
The flip side of this is that it is much harder to evolve a technology if it reaches mass adoption too quickly, as Gosling acknowledged: “Being successful turns out to be a problem because there are now billions of lines of Java code out there. Within a couple of years of Java being launched, it became really clear that we couldn’t change anything that would break anyone’s code. So that puts a real crimp on just how crazy you can be in evolving things.”
The Runtime Is the Operating System
At the moment, though, Wasm, while it is building momentum, doesn’t have these problems.
“When we think about using Wasm for general-purpose computing, whether it is in the browser or for a server, it doesn’t come with all the baggage,” said Crilly, of F5. “It doesn’t come with POSIX, for one thing, and it doesn’t default to knowing anything about files.
“That’s actually quite an alarming abstraction to go without, but the more you think about it, the more you realize that that was just an abstraction that was useful in the office space of the 1970s, when Unix and POSIX were getting matured. We are way more sophisticated about storage and abstractions in general then we were then, so defaulting to files as our storage abstraction is kind of dumb.”
There are also tremendous potential advantages to starting over in thinking about operating systems. For data, for example, “we can dispense with traditional data constructs and treat each chunk of raw data as a true object for any operations,” Crilly said.
This paradigm, he added, would mean “pushing the result back out to whatever data store we need, in whatever format we want, with the help of a plug-in module. All the way down the stack, all of the preconceived notions of what an operating system is can fall away, and what’s left is a runtime — the most essential element of computing. In other words, the runtime is the new operating system.”
The Wasm Component Model
The component model proposal for Wasm is one way this vision might become a reality. It builds on top of WebAssembly modules, which became an official standard in 2019. The component model is a new Wasm binary format, which essentially adds metadata around a WebAssembly core module. So there can be multiple modules within a component.
The component model gives you two things — language interoperability and composability. A component encapsulates a full WebAssembly module, and you can talk to it using imports (what the component needs in order to run) and exports (what you’re allowed to call on from the component).
The component model is based on shared-nothing linking, meaning that it only imports and exports functions and immutable values, but not memories, tables or mutable globals. It is somewhat similar to Unix pipes connecting separate processes, or HTTP APIs connecting separate microservices.
Taking this approach eliminates an entire swath of potential supply chain-style attacks. Moreover, using function imports to directly call across shared-nothing boundaries reduces the communication overhead you typically see in shared-nothing architectures due to system calls, context switches and extra copying.
The component model also eliminates several points of friction with Wasm modules, according to Bailey Hayes, CTO of Cosmonic, a Wasm Platform as a Service. For one, Hayes told The New Stack, “those imports and exports use higher-level types, so now I can pass in things like Strings.”
While it was possible to do this before using, for example, Wasm bindings, it was cumbersome, and so making this easier is clearly a win.
Likewise, the lack of language interoperability with WebAssembly modules was another cause of friction. Technically, the Wasm bytecode is “just a bunch of numbers in a trench coat,” Hayes told us. “It really is just a bunch of i32s, integers and float types. It is able to call function handles that the host gives it — that is what enables it to do more things.
“The component model doesn’t change that aspect, but what it changes is the API, what we call the interface types; there is now an interface types definition that is more than just a bunch of numbers, and it creates what we call the canonical ABI. This is how I can take two components, link them together and have them talk to each other.”
This is also what allows us to generate language bindings in whatever language we are working in. “The Python representation of a string and the Rust representation of a string are different,” Hayes said. “So I need a way of lifting and lowering, which is how I go from one to the other. And that is defined by the component model.”
Hayes believes that the Wasm component model will ultimately become our new unit of compute. “This next wave of compute will no longer focus on the virtualization of Linux-like containers and will instead be defined by a WebAssembly representation of just our business logic,” she said.
The reason for this, she suggested, is that “the component model gives us a new abstraction that we haven’t had before. It’s one of those things that I believe will finally let us bring down silos across the technology ecosystem.”
She explained further: “Often what you see in the industry is, ‘This is the Go native version of this other Rust or C++ library’ — you see this in every language ecosystem. We’re really just duplicating the same work and, in my opinion, it is just a waste of human effort and time.
By contrast, the component model lets technologists “build the best component for the job, the one that has the best API and is the fastest, and then you can just use it as your library, whatever language you are in. I think it will be a real force for innovation.”
Her enthusiasm for Wasm is infectious, and this really is exciting technology, but Crilly sounded a note of caution.
“There are some challenges with this approach,” he said. “One is, do we end up stifling innovation, because how does one KeyVal, for example, distinguish itself from another if they have to follow the same API? My other worry is that there will be a rush to bring all the POSIX abstractions to WebAssembly via the component model.
“I don’t want us to sleepwalk into 1970s operating system paradigms. We can do so much better, and I really want developers to think hard about this when they start to pick up WebAssembly as a technology.”