WASM All Things - A Tour of the WebAssembly Ecosystem
Hi folks,
It's Kostas again from the Core Team with the second part of my WebAssembly series. For a quick recap of the last week’s article, I discussed the bottlenecks of working with multiple client libraries and the novel idea of compiling mgclient
to a WASM module, effectively mitigating the inter-op dependencies on the bindings. Today, I will dive deeper into the WebAssembly world by discussing a few key ideas behind WASM and its ecosystem, and I will start with a question: how to compile a C library to a WASM module?
To do it, we need a compiler, and Emscripten SDK is a compiler toolchain (based on LLVM) that compiles a C program to a WASM module that can be consumed from the browser or any engine that runs JavaScript (like node, V8, etc.). This raises a key question: what happens to system libraries like POSIX? After all, the browser is a restricted environment, and its access to low-level system interfaces like IO, threading, etc., is limited. Moreover, POSIX is not platform independent, thus contradicting the core value of WASM, which is to be truly platform-independent. The key answer to that question is that the system libraries are emulated. Emscripten doesn't only produce a WASM module file but also a JavaScript file that emulates the behavior of the system calls.
Notably, since the Emscripten compiler also produces a JavaScript file, then consequently the consumer of the module is bound to the limitations of JS. This might work well with the browser, but it won't, let’s say, Ruby or Rust. The reliance on system libraries being exported as JavaScript is the Achilles heel of WebAssembly because it implicitly imposes the execution requirements of JS. Thankfully, the community has recognized the necessity of porting WebAssembly beyond the edges of the browser and came up with WASI (WebAssembly System Interface). Simply put, WASI provides a complete sandbox for system-like features. It is bundled on a complete SDK capable of producing a standalone WASM file that can be consumed by any WASI-compliant runtime, thus providing a true, seamless inter-op like features on any execution environment. Moreover, WASI provides a runtime of its own, which can execute standalone WASM files by pretty much sandboxing the WASM module.
The interesting thing is that Emscripten also supports a form of standalone compilation to WASM. That is, it omits any system library JavaScript glue code and instead uses WASI when it makes sense (yeah, this is very vaguely written because the docs in Emscripten themselves are not very clear on the matter). However, their WASI support is limited, and I would go with WASI SDK for true standalone WASM modules. My two cents about Emscripten are that it might fully support WASI in the future, even though it was developed to be completely independent. After all, it already supports a subset of it, so why not go full WASI compliant?
And now for the cherry at the top and the missing element mentioned in the previous article - wasmer
. It is a WASM runtime that supports WASI and is available as a library in many languages (Java, go, PHP, Ruby, etc.). With wasmer
, we could, in theory, replace all the binding technologies (JNI, etc.) with a single runtime that has the same universal semantics. The only thing that slightly changes for each supported language is the API (to conform to the paradigm of each language).
With all the WebAssembly information we went over in this article, we built a solid foundation to finally discuss jsmgclient
, the Memgraph's first WASM-based client adapter. Buuuuut, for that, you will need to read the last part of the series.
Peace out!