That is what this whole trend is all about, replicating application servers with WASM.
Every time I need to dive into k8s stuff, I can only think "this was so much easier when configuring WebSphere and EAR deployments".
That is what this whole trend is all about, replicating application servers with WASM.
Every time I need to dive into k8s stuff, I can only think "this was so much easier when configuring WebSphere and EAR deployments".
But the similarities are shallow at best and tied you into a single VM.
Saying “this whole trend is all about replicating application servers with WASM” makes it sound derivative. I mean, yes, but only yes in the same way “cloud computing is just replicating large remote shared mainframes”.
And applications get tied to the WebAssembly ecosystem, it is also a single one.
For one, the idea is that it should be fairly simple to compile an arbitrary program to WASM, allowing you to use a far wider variety of languages.
In this case, it’s more akin to “docker with extra steps” as opposed to “docker but you can only hire Java devs”
Wasm is a refinement of the ideas in the JVM, with a couple good JVM on Wasm solutions already existing. The best of which is CheerpJ.
Instead of referencing NestedVM, you should link to GraalVM which I know you are aware of.
The main difference with regard to compiling “arbitrary” programs between the JVM and WASM is that the JVM doesn’t have untyped linear memory like WASM does. WASM isn’t type-safe within the linear-memory regions (which is what allows C-like languages to be compiled more directly), whereas JVM ensures type safety for all objects.
Saying that “WASM is a refinement of the ideas in the JVM” is simply wrong, they have different design goals and therefore implement different design trade-offs.
As you say, it can be trivially emulated, no reason that linear memory couldn't be implemented on the JVM using an array of primitive (char,int,long).
The Wasm VM is more generic and has a better capabilities security model than the JVM. Had the JVM been more like Wasm (signed and unsigned primitives, capabilities model), it would have been a natural compilation target for sandboxing native code.
As Wasm gets more features it becomes more like the JVM (GC, reference types, component model). Eventually Wasm will subsume all the features that differentiates them.
Why is that different?
WASM is pretty different to the JVM. The JVM deals with a lot of higher level constructs like objects, constructors, virtual methods, the GC etc. Which is fine if the language you’re hosting works in that way.
WASM is more like assembly - the raw intrinsics used by a hypothetical WASM CPU. So you can compile a lot more stuff to it, because it’s a more natural target than a much, much higher level VM like the JVM.
On the browser side, you could maybe make a ChromeOS style argument of just wanting to run everything in a browser no matter what, it's nice for it to be sandboxed etc. But if you look at what your Postgres is doing it's sort of a Linux VM, and you can run those already at full speed: that's WSL and there are various solutions on macOS like Docker Desktop.
On the server side, the reason nobody bothered trying to run Postgres on the JVM before Graal is that it's unclear what the benefit is. Security? Processes and kernel isolation seems to work well enough on the server, and anyway Postgres is a highly trusted component anyway. CPU independence? That hasn't been useful since stuff like SPARC died, we are now just starting to see ARM chips appear on the server, but compiling native code for both intel and arm isn't hard and Linux distros have the infrastructure to do it for a long time already. For custom servers, well, not many are writing them in C/C++/Rust anyway these days. RISC-V remains mostly theoretical.
To what extent is this doing it because it can be done, vs delivering real benefits? My mind is open but the low level nature of the WASM instruction set also means the VM can't offer many benefits to the programs inside it, nor the users outside it.
The JVM has historically and famously sucked at sandboxing untrusted/partially trusted code. The JVM also isn’t a suitable compilation target for arbitrary and existing codebases.
WASM is built to sandbox untrusted/partially trusted code. WASM is built as a compilation target rather than a complete hosted VM with bells and whistles.
There are advantages and disadvantages to this. One advantage is language-agnosticism. Another might be around the ability to run user-supplied untrusted code in a much safer way. See Cloudflare functions.
One disadvantage is the lack of bells and whistles.
So, the answer to “why is this different to the JVM” is that.
We need to drill into this a bit more, because the WASM ecosystem can certainly learn lessons and do better than the JVM but this isn't quite the right set of lessons to learn.
The JVM spec was written from day one to sandbox arbitrary and partially trusted code. The SecurityManager architecture is now being removed, but that's a big project exactly because it was deeply integrated into everything. It's also embeddable and a compilation target (it interprets bytecode), and later it was extended with features designed to make it more language agnostic as well at least for everything at the same level of dynamism of Java or higher (so indeed not C/C++ but yes for most other langs).
So the interesting thing to debate here is not really the design goals, which are very similar, but what concretely will make WASM more successful at achieving these goals.
For example, what made the SecurityManager difficult wasn't something fundamental to the JVM but rather that code which is both useful and sandboxed needs APIs that let it do privileged things in controlled ways, and a lot of the bugs were in those API implementations or on the boundaries. That's especially the case on the desktop where sandboxed code had to call into a lot of OS libraries.
On the web this problem is solved with the browser makers exposing JS/renderers to WASM or just saying do the tricky stuff in JS, and then wrapping the whole thing with kernel sandboxes and IPC to handle the fact that the JS/WASM sandbox itself will inevitably fail in the same way. In other contexts this, well, doesn't seem to be solved, really? The moment you start exposing APIs to the WASM code you face the same problem. Also these days you have spectre to think about, so maybe you need a separate process sandbox anyway. Alternatively you can do what the GraalVM guys are doing (in their EE) and using Intel MPKs but that's pretty advanced and I didn't hear about anyone else doing that.
Now there are still some crucial differences! The JVM wanted to allow sandboxed code to interop smoothly with higher privileged code. This opened up a bunch of reflection-based bugs whereby you could reflect your way to the SecurityManager and switch it off, confused deputy attacks and so on. There's no equivalent in WASM, but that's partly because (current?) WASM doesn't really try to define a fine grained permissions model or a way to mark some bits of code in a program as more privileged than others. It also doesn't provide a large set of pre-implemented APIs. The sandbox is whatever the developer exposes to the context. This doesn't make WASM stronger, it just means it punts the really hard bits to the user i.e. browser devs. GraalVM's new JVM sandbox (not SecurityManager based) works mostly the same way, as do process sandboxes so this is definitely the trend, but of course there was a reason the SecurityManager was created that way and it's because it requires way more code and work by the developer to sandbox code if you don't have support for tight mixing. So maybe the sandboxes that do exist will be stronger, but there'll be less sandboxing overall and permission scopes will be much wider. Is that the right tradeoff? I'm not totally sure it is but eh, people really like all-or-nothing and that's the way the industry is heading now.
At any rate that discussion is a bit academic, because you can't do an OOP capabilities type architecture in C anyway.
What about language agnosticism? Again the hard part here isn't having a common bytecode - CPUs already provide that - it's all the engine bindings and semantic alignment required. If you want to pass a std::time into JavaScript then something has to bridge that gap, if you want to call into a dynamically typed language from a statically typed language, then something has to generate interfaces for the compiler to check against and so on. Here I don't see what WASM has to do with anything really, it's just not in scope. Compiling a Python interpreter to WASM doesn't make it any easier to call Python from C++, or Java, or JavaScript. The SOTA there is Truffle/JVM by far.
Wasm can learn from the JVM for sure, but if you went almost 30 years back in time, you would have some great tricks to teach the JVM, learned from Wasm.
Consider .NET / CLR for another example. Like JVM, it also deals with objects, methods etc conceptually on bytecode level. But it also deals with raw pointers and pointer arithmetic and other such stuff. As a result, you can efficiently compile e.g. C into that bytecode. So wasm isn't really new in that sense, either.
You can run Postgres using WASM in two different ways[1][2]. That’s a non-trivial codebase.
1. https://www.crunchydata.com/blog/learn-postgres-at-the-playg...
You can compile arbitrary programs to WASM, like you can compile arbitrary programs to x86 or ARM. It’s effectively a CPU target. You can take the whole of Python and SQLite, compile them to WASM and run a web framework on top of that via WASM in the browser[1].
If those programs utilise specific os-level behaviour that can’t be shimmed, or explicitly throw an error when being compiled to WASM then of course they won’t work without modifications.
Meanwhile, the JVM is not anything like a CPU target. It’s a very high-level VM designed for a particular type of gc’d and jitted language.
If the model works, why shouldn't there be competitors and wide spread adoption?
WASM likely won’t convince all languages to switch to its bytecode by default. Its adoption story requires enough people to maintain this non-standard compilation pipeline.
Which is fine, but beyond the bytecode, the productivity will only be maintained if it offers an equal or superior interface to POSIX. Right now, WASI is not it. A lot of basic elements are experimental, like file seek, multi-process, threads, SIMD, GPU programming…
People will believe the hype, miss the caveats, use it at work, and have their project fail. Companies will blacklist the technology.
In my mind, it is too early for them to be so publicly dithyrambic. All WASM publications should link to a page that details all WASI features that are still experimental.
.NET/Java/Clojure, maybe not. Ruby and Python work via an interpeter for the platform, just like they do on JVM/.Net, except that, unlike JVM/.NET, in both cases they can use the normal C-based interpreter, compiled for WASM.
There is no world where people are just grabbing an existing app and saying "hey, I'm gonna drop this into my wasm runtime real quick"
This is great for running existing "native" type code compiled from C/C++/Rust but its profoundly unsuited to the kind of development that most application or service developers do, which is in higher level languages with automatic memory management, monitoring / profiling services, etc. All of which either have to be re-invented in the WASM world, or run inside the WASM container at 2x or more the runtime/energy cost. And for what benefit?
It's one thing to get a game engine running in a web browser. Neat hack / potentially decent way to ship a client.
It's another thing to try to repackage existing working, relatively well engineered, server runtime systems inside it for almost no benefit at all.
TDLR: WASM is not a universal VM appropriate for server apps. It is a solution for shipping a certain kind of application in a certain circumstance. There are other, better, solutions for "containerizing" services.
Finally, after 25 years in this industry, the world I want to head to is higher level, where things are managed declaratively with explicit, visible, well described rules and relations and logic. WASM seems to me to push the other direction. Black boxes of fairly low-level code, each reinventing its own runtime wheel and with almost no visibility from the administration side of what's happening in there. I find that kind of sad.
I mostly agree with your overall point though. I’m not making the point that WASM right now (or even later) is the future of deploying backend services, however it is somewhat of a universal VM. If it’s a useful one is yet to be seen.
Putting it more clearly: Most services development is done in languages that have their own virtual machine (JS/TS, Go, JVM, Python, .NET). In what world does it make sense to run that VM inside another VM?
Finally, I think the experiences over the last 20 years around .NET and the JVM should have shown there is in fact not really such a thing as a truly universal abstract VM. A well-written VM tends to be written towards supporting the language(s) it is built for.
... Not unless you're willing to throw away almost all added value, and then you start looking like WASM. And then what's your value beyond native code, running on the hypervisor and/or in a container?
(There are in fact proposals for adding GC hooks in WASM. I'd have to spend some time reading up on them to evaluate whether they address my objections.)
b) Kubernetes is the platform as well as the application server.
- IDE code completion
- Can be machine generated/updated via the GUI management administration and graphical tooling on IDEs
Good luck doing that with YAML.
1 and 3 are actually foundational to how k8s works.
Forgive me for saying this, but I’m getting a “i don’t want to invest any effort understanding anything and so Kubernetes is bad” vibes from these comments.
It’s not a particularly pleasant experience to discuss anything with you, as after you make a particularly vapid comment that is naturally rebuffed you seem to just try to make snarky replies rather than engage.
Please understand that if you post your hot takes here they may be discussed and challenged, and if you don’t want this then I would refrain from initially commenting.
In response to your comment: They do. All Kubernetes resources are typed with JSON-schema definitions. Because of course they are, how else would kubernetes validate anything. https://kubernetesjsonschema.dev/
Anyone who’s used k8s at all knows this, if only from the error messages. From this you get autocompletion and a wide ecosystem of gui configuration tools that work with everything, including custom resource definitions, which is really cool.
I used to like lens (https://k8slens.dev/desktop.html), but now I use the k8s plugins from IntelliJ
Which I don't use hence why I wasn't aware of it.
> The Dunning–Kruger effect is a cognitive bias whereby people with low ability, expertise, or experience regarding a certain type of task or area of knowledge tend to overestimate their ability or knowledge
https://en.m.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effec...
That’s legitimate but, especially for open source developers, overkill and it pulls in a ton of maintenance work (e.g. I have several apps with a ton of CVEs in components which were never used but can’t be removed without breaking things, and thousands of lines of XML configuration which has to be analyzed to look for intentional customization to upgrade to the release version which has been patched. Now, maybe that’s doing it wrong but that’s multiple separate Java specialist development shops so it’s not just me being dense.).