Rust and C++ Work Better for WebAssembly
Before we cover what happens before WebAssembly can seamlessly support most, if not all, of the principal languages in use today, the status quo needs to be stated: we are still a ways away before the developer writes their code with zero extra configuration necessary for Wasm modules in order to deploy an application simultaneously across a number of different environments, ranging from cloud deployments to IoT devices to on-premises servers.
Different applications written with different programming languages should be able to function within a single module. Essentially, a microservices-packed module should be able to be used to deploy multiple services across multiple disparate environments and offer application updates without reconfiguring the endpoints. In theory, it is just a matter of configuring the application in the module so that each environment in which the module is deployed does not have to be reconfigured separately once the work is done inside the module.
WebAssembly only supports Rust and Go among the RedMonk top-20 most popular languages for WebAssembly apps running in the browser, the CPU core, and on Fermyon’s Spin SDK. A component model that can accommodate even Rust and Go, much less all of the languages on a single Wasi target, has yet to be finalized.
So what is the holdup?
It largely comes down to that last WebAssembly System Interface (WASI) layer and each language’s interaction with it.
To ensure different programming languages can work together within WebAssembly modules, they all need to create a translation layer. This layer helps convert their unique system calls into a format that WASI can understand, Torsten Volk, an analyst for Enterprise Management Associates (EMA), said.
“System calls are the requests a program makes for resources like storage network, or computing power. While this might sound straightforward, it’s actually quite complex,” Volk said. Each programming language has its own set of system calls, and these can be fundamentally different from one another. They need to be carefully adapted so that WASI can understand them, Volk said.
As Volk explained, several things can go wrong when a programming language has a system call designed to access the file system:
If WASI doesn’t directly support this system call, the translation layer has to figure out how to map it to a WASI-compatible call. This requires a deep understanding of both the programming language’s system calls and the WASI API, making it a complex task.
Some system calls might ask for more system access than WASI can provide. These calls might not be feasible to translate directly and could require complex workarounds.
The process of translating system calls takes time and uses infrastructure resources. This could make it challenging to maintain consistent performance. In essence, while WASI provides a way for different languages to interoperate within WebAssembly, the process of adapting each language’s system calls to be WASI-compatible can be quite complex and resource-intensive, Volk said.
The recently released roadmap for WebAssembly by the WebAssembly Community Group (CG) and the WASI Subgroup within the W3C for WebAssembly Core, WebAssembly Component Model, WASI and other WASI-based interfaces did cover language support. The Component Model proposal, developed on top of the core specification, includes the WebAssembly Interface Types (WIT) IDL, while WIT is the language of high-level types that are used to describe the interfaces of a component (the Component Model adds high-level types with imported and exported interfaces, making components composable and virtualizable, as Bailey Hayes, director of the Bytecode Alliance Technical Standards Committee and a director at Cosmonic, wrote in a blog post. This is important for allowing different programming languages to function in the same module because it allows for the creation and combining of components that were originally written in different programming languages, Hayes wrote.
“This standardization also fosters better collaboration between language tooling that creates components from various languages and hot-swappable modules defined by the WebAssembly System Interface (WASI),” Liam Randall, CEO and co-founder of Cosmonic, told The New Stack.” What this means to developers is that we can now use code from across our language silos, creating a powerful ‘better together’ story for the WebAssembly ecosystem.”
Rust Never Sleeps
Meanwhile, the most compatible languages for WebAssembly applications in production are Rust and C++ or C. That said, of the top 20 languages in analyst firm RedMonk’s language ranking, 16 have at least basic browser support.
“It is no coincidence that statically typed languages that do not require garbage collectors, like Rust and C/C++, were among the first languages to add WebAssembly as a target,” Hayes said. “Adding a new bytecode target for a virtual stack machine is more straightforward with systems-level languages that do not need to compile in an interpreter or garbage collector. “
But what makes Rust different from the rest is that it enjoyed a co-evolution with WebAssembly, Hayes said. Many of the Mozilla engineers working on WebAssembly within the SpiderMonkey engine were also part of the growth and development of the Rust language, Hayes said.
The primary goal of WebAssembly is to produce a bytecode that is extremely compact allowing for tiny and load time efficient binaries that are also memory-safe and sandboxed, Hayes told The New Stack. Rust has zero-cost abstractions and is attractive to engineers invested in creating memory-safe programs. “In many ways, WebAssembly and Rust appeal to each other’s goals and key strengths,” Hayes said.
Rust is downright hard to learn for many if not most developers or anyone who just wants to code. Yet, Hayes noted how Rust is consistently ranked the most loved language by developers.
“Rust was not on my radar for languages to check out until it reached its first stable release in 2015,” Hayes told The New Stack. “The interesting thing about 2015 is that it also happens to be the year WebAssembly design work began.”
C was also the original language targeted for WebAssembly support, and the group working on the specification paid close attention to the C/C++ ecosystem, Butcher noted. “Rust, like WebAssembly, was originally started at Mozilla and grew up alongside WebAssembly,” Butcher said. “Some of WebAssembly’s most active developers also worked on key pieces of the Rust ecosystem. So the technologies co-evolved.”
Once a component standard is finalized for Wasi for the backend, Python support will be especially welcome. This is because Python’s big appeal lies in the massive number of easy-to-use libraries that often get developers to the 80% or even 90% without having to write a significant amount of code, Volk told The New Stack. “Assume I want to take this article and store it in a NoSQL database, such as MongoDB or Cassandra. First, we could use the Selenium library to find and retrieve the article on the TNS website and then we might leverage Pandas for identifying and storing the individual components of the article, e.g. headings, images, text, links, etc. in a handy data frame,” Volk said. “Finally, we could use the Cassandra-driver library or PyMongo to connect, authenticate, and write the article to our NoSQL database of choice. If we could get all of this to work on Wasm, we could share and sell our new app with anyone and without having to worry about the target cloud.”
At Fermyon, Python support “is our focal point,” Butcher said. “We recently released an updated Python Spin SDK, and are already plowing ahead on a new version,” Butcher said. “We won’t slow momentum until we can support the common libraries and workloads used in modern Python AI and data processing.”
This challenge is very similar to the early days of Kubernetes when saving app state, storing app data, ensuring app performance and interacting with external systems “was still tricky,” Volk said. “Now we need to simply figure out the current limits of this approach within real-life projects and continuously push the boundaries, just like we did for Kubernetes,” Volk said. “But as a reward, we could ultimately store the entire application, including its server and container runtime, inside of a container registry for turnkey deployment.”