Hacker News new | past | comments | ask | show | jobs | submit login
Wasmer 3.0 (wasmer.io)
305 points by syrusakbary on Nov 23, 2022 | hide | past | favorite | 183 comments



Cross-compiling to different targets with `create-exe` command is a very intriguing idea.

> In Wasmer 3.0 we used the power of Zig for doing cross-compilation from the C glue code into other machines.

> This made almost trivial to generate a [binary] for macOS from Linux (as an example).

> So by default, if you are cross-compiling we try to use zig cc instead of cc so we can easily cross compile from one machine to the other with no extra dependencies.

https://wasmer.io/posts/wasm-as-universal-binary-format-part...

> Using the wasmer compiler we compile all WASI packages published to WAPM to a native executable for all available platforms, so that you don't need to ship a complete WASM runtime to run your wasm files.

https://wasmer.io/posts/wasm-as-universal-binary-format-part...


one thing to note is that the performance is still on the level of normal wasmer exexution and thus inferior to natively compiled code in most instances


> thus inferior to natively compiled code in most instances

Do you have a source for this claim? Using a JIT with AOT binaries (which is what this seems to be) can sometimes be very beneficial. It's like doing PGO without the manual work of doing PGO properly.

I'm sure the JIT can make poor decisions sometimes, but I would want to see a comprehensive set of benchmarks, like The Benchmarks Game and TechEmpower showing this. Benchmarks aren't always reflective of reality, but good ones are usually more insightful than random opinions.

The only Wasmer benchmarks I could readily find were from three years ago, and that was before Wasmer 1.0, let alone 3.0.

EDIT: Reading more... maybe `create-exe` doesn't include the JIT at all, so it is just making an AOT binary from the source WASM? In which case, benchmarks are just as necessary to understand how it affects performance compared to a normally-compiled native binary.


Here is an extremely unscientific benchmark using the Takeuchi function and Trealla Prolog:

   $ make wasm
   $ wasmer create-exe tpl.wasm -o tpl-wasm
   $ time ./tpl-wasm --consult < tak.pl -g 'time(run)' --ns
   '<https://josd.github.io/eye/ns#tak>'([34,13,8],13).
      % Time elapsed 1.39s
   real    0m1.403s
   user    0m1.333s
   sys     0m0.070s

   $ time tpl tak.pl -g 'time(run)' --ns
   '<https://josd.github.io/eye/ns#tak>'([34,13,8],13).
      % Time elapsed 0.448s
   real    0m0.473s
   user    0m0.463s
   sys     0m0.010s
WASM is about 3x slower. In general I've found it to be 2-3x slower, at least for my use cases. I also tried the LLVM compiler instead of Cranelift but it was slightly slower.


In my tests (simple rust benchmarks) it was about 30% slower. Ab large part of the 1.4 is probably startup time. So it's not that bad either.


Oh yeah, it's definitely not bad. I'm quite happy with it. I imagine I'm hitting on some corner cases here that aren't really indicative of the average user. Thanks for the comparison.

My reading of the numbers is that the startup overhead is about 13ms in my example, quite fast. Shout out to Wizer for greatly reducing the startup time.


Certainly interesting, but I'm not sure how well the performance of a prolog interpreter maps to other use cases.

That benchmark looks too short to be a useful measure of how JIT influences performance, otherwise I would ask how the regular Wasmer does in that benchmark too (since it seems like create-exe doesn't include a JIT).


Wasm also can't do computed goto for interpreters, so it's at a disadvantage for this benchmark in general


Is the used interpreter built with computed goto?


Switch tables tend to be computed goto based


Is the interpreter we're talking about built this way?


Honestly I can't really say (I just ported it to WASM :-)), but here's more or less the start of the query loop: https://github.com/guregu/trealla/blob/main/src/query.c#L173...

I believe it's a bytecode but I know that function pointers are involved at least with the built-in predicates (see predicates.c).


Even if you write if...else a smart compiler will turn it into a switch table.


Could you show an example? A Godbolt link would be nice!


I guess it's safe to assume that if they're not providing benchmarks claiming it's faster than native, then it's slower (and that's ok)


I don't commonly see mainstream programming languages, compilers, or runtimes providing comparative benchmarks for themselves these days, so I don't consider that a safe assumption at all. It would certainly be nice if Wasmer did provide some benchmarks.


There are lies, damn lies, statistics and benchmarks, but I do take you point. It does give an idea but is the main goal of the project speed or portability (genuine question)?


The usefulness of portability is generally less the more it sacrifices performance.

I also think of WASM as a tool that could provide a useful security boundary.


Which should be mostly fine unless you are doing some particularly slow things or need hardware acceleration that is difficult to get via wasm. For lots of code, your CPU is going to be idling while it runs. Wasm is fine for that type of code. It will idle slightly less. You won't notice the difference.


Can someone ELI5 what problem this solves? I think of WebAssembly as being a tool for getting code written in <random language> to run in a web client. Can't I already run code written in <random language> on a server that I control? Heck, PG went on at some length in one of his early essays about how that was one of the great things about the Web: you could use any language you wanted on the server. Even Common Lisp...


WASM is also useful for distributing a single binary blob that runs on different Operating Systems and CPU architectures, instead of 'stamping out' NxM native executables. This area overlaps more with Java and .NET (but with more/different language options) than 'an alternative to JS in the browser'.

For instance I have a C++ shader compiler which includes some massive 3rd party libraries (glslangValidator, SPIRVTools and SPIRVCross) which takes forever to compile, so distributing in source code form is not really an option, and the only alternative is to ship precompiled binaries for each supported OS/CPU combination. Currently I do this via GH Actions, which kinda works, but just building a single WASM blob and shipping that to users (who then would need to install one of the WASM runtimes though) sounds kinda interesting.

PS: WASM may also be useful as universal plugin format. For instance the new Microsoft flight sim uses WASM instead of scripting or native DLLs for modding:

https://docs.flightsimulator.com/html/Programming_Tools/WASM...


i'd really wish game mods would be run with WASM. the current solution of downloading native code from third party websites always makes me highly uncomfortable.


Java’s GraalVM can do plenty of languages, on top of running managed ones much faster. I don’t see novelty here.


Well, the point is not in some novelty, but that it does a similar thing as an open standard, with more than one vendor and community behind it for runtimes, tooling, etc., that it doesn't come from Oracle (which is an extra bonus), and with compatibility with the web and bigger boost behind it than Graal ever achieved thus far to boot.


Java bytecode is an open standard with more completely independent implementations than wasm, but it is slightly higher level. Graal (truffle) uses ASTs mapping to Java language primitives as a basis (in a way sorta similar to wasm, as that is not really a byte code).


WASM also takes a whitelisting approach to security rather than a blacklisting like the JVM. Java applets had lots of security issues over the years, whereas WASM provides much better isolation. Overall JVM or CLR always seemed too heavyweight for many use cases.


Java had an extremely advanced and strict sandbox for many years.

It offered of course also the possibility to blacklist everything by default.

The problem with such a granular sandbox is that it's too complex for most use cases.

When you need to whitelist any and every call to the outside world this becomes very tedious.

That's why Java now removes the sandbox…

https://inside.java/2021/04/23/security-and-sandboxing-post-...

Let's see how this works out for WASM.

I guess: Without resorting to using some language(s) with build-in support for capability security a whitelist based sandbox approach won't ever work without issues.

First of all you can forget about C/C++. Everything in this languages assumes free access to the system.

Rust does not have any support for capabilities either (yet, and for the years to come at least).

The best current WASM sandbox implementation, which is in WasmTime not Wasmer, is not more than a FS block. (And the memory safety guaranties you get in any VM language, of course).

https://docs.wasmtime.dev/security.html

I don't find any such feature mentioned in the Wasmer docs. It seems completely without any sandbox! (To stress it once more: All VM languages are memory safe. That's not sandboxing. All the "sandboxed by default" claims are misleading, at least).

https://github.com/wasmerio/wasmer/issues/221

That even people here on HN believe in the currently unfulfilled WASM security promises shows only how good the WASM marketing is. This should make you even more skeptical. One should never over promise on security! Java had to learn this the hard way over many years (as their sandbox had have holes in the past, and was also almost impossible to correctly configure).


> I don't find any such feature mentioned in the Wasmer docs. It seems completely without any sandbox!

That's not correct. Wasmer aims to be a fully sandboxed WebAssembly Runtime. Wasmer WASI implementation is also fully sandboxed.


> Wasmer WASI implementation is also fully sandboxed.

Could you please link to some authoritative documentation for that?

As I said I don't see this in any docs or GitHub sources.

The point is: It's irrelevant what they "aim for". The only interesting thing at the moment is the status quo.


Sure thing. Check the WASI README (a section was just added to clarify your comment)

https://github.com/wasmerio/wasmer/blob/master/lib/wasi/READ...


Thanks for the effort!

I still don't get it.

What does "the aim to be 'fully sandboxed'" mean in the light of "support [of] standard I/O, file I/O, filesystem manipulation, memory management, time, string, environment variables, program startup etc."?

What are "secure systemcalls"? What does this mean on the technical level?

How is the simple FS access filter (something you get form std. Unix FS access rights since 50 years) something special here, or even considered "fully sandboxed"?

(I get the broader idea of capabilities. But I would see this only as a minor implementation detail in the current state).


Basically, what we mean by sandboxed is that the application would not be able to do anything harmful to your system unless explicitly allowed (similar ethos as Deno, compared to NPM).

Let me explain a bit more how:

* stdio / file io: thanks to Wasmer VFS and the WASI mapped dirs, the application will only able to access to the directories explicitly defined by the user when running a program. Any file/dir access outside of the allowed directories will throw an error (both by design of WASI and by our implementation of it). Note: by default stdout/stderr will be piped but that can also be easily customized.

* Environment variables: no environment variables can be accessed unless explicitly specified to our CLI (or SDKs)

* Time: we consider time access (get) to be harmless (WASI don't allow setting the platform/OS time, so we don't have to worry about that)

> What are "secure systemcalls"? What does this mean on the technical level?

It means system calls that we consider harmless to execute. For example, getting the current time (unix timestamp) is considered harmless by our WASI implementation (it should be easy to even shield that, if needed), but accessing a file could be harmful (that's why we ask for permission first).

Of course, no software is free from bugs that could jailbreak the sandbox, specially after Spectre and Meltdown. So having something to be "fully sandboxed" is an infinite game.

But our aim is there, nonetheless :)


Thanks for the reply! I appreciate that.

> Basically, what we mean by sandboxed is that the application would not be able to do anything harmful to your system unless explicitly allowed (similar ethos as Deno, compared to NPM).

So how is this different to the mentioned (obviously failed) JVM sandbox?

It's exactly the same concept as I see it. "Security" fully depends on (complex!) configuration.

What possibly could go wrong here…

> stdio / file io: thanks to Wasmer VFS and the WASI mapped dirs, the application will only able to access to the directories explicitly defined by the user when running a program. Any file/dir access outside of the allowed directories will throw an error (both by design of WASI and by our implementation of it). Note: by default stdout/stderr will be piped but that can also be easily customized.

So basically you've implemented file access rights.

With multiple additional layers of indirection and a lot of additional code. (TCB anybody?)

Sure, this looks very promising and innovative. What possibly could go wrong here?

How does this prevent unwanted information exfiltration given std. I/O and networking works?

Also, how does it prevent that a rouge / hacked app for example encrypts all files / databases it has regular access to?

> Environment variables: no environment variables can be accessed unless explicitly specified to our CLI (or SDKs)

> Time: we consider time access (get) to be harmless (WASI don't allow setting the platform/OS time, so we don't have to worry about that)

How is this different form std. Linux "capabilities", and the Linux syscall filter?

> Of course, no software is free from bugs that could jailbreak the sandbox, specially after Spectre and Meltdown. So having something to be "fully sandboxed" is an infinite game.

Getting the sandbox tight and close is not the problem imho.

This was done several times already (with mostly OK-ish results).

The problems start when you need to dig holes into it. (And you need holes, otherwise you're so "secure" that you can't do anything meaningful).

I still don't get how a new "whitelist only" sandbox will not end up in the same fundamental issue like the ones before it. When "security" is crucially depended on complex configuration it's very likely that there will be unintended holes because someone didn't get the config right. (Just think about why almost nobody is using SELinux even it gives you even better guaranties then WASM currently).

Java shows this problem also very well: It died on the client not because there were technical loopholes in the sandbox. There were almost none of this kind! The problem was the overly complex sandbox config (with to be honest additionally quite stupid defaults in the beginning) that nobody got right, and security issues popped up constantly therefore.

So you don't even need to think about Spectre and Meltdown kind of attack vectors.

After years (or even decades) there is still no guaranty that people get things like Linux "capabilities" or even std. FS access rights correct. Now the same people are expected to get some other features, that do basically the same, right?

I know already how this will end up… And this will blow up very painfully right into your face after you have spit so much promises about the superior security of your approach!

Don't be stupid, learn form the Java story. (And no, you're not anyhow better. If you think that, you lost already, and your ship is going to sink with a lot of skit for sure).

---

I think the only way to get capability security right, and especially usable by mere mortals in the first place is to make it a fundamental part of the languages used.

Rust is light years away form that, though… (And others don't even have the basic enabling features for that.)

The languages that tried something like that in the past are by now dead since a long time. (Like the E programming language)

Though I put high hopes into the upcoming Scala features in this regard.

But nevertheless those are way ahead of any other (real) language even there a usable system is also still years away. For reference:

https://docs.scala-lang.org/scala3/reference/experimental/cc...

(This will give you all the features of Rust plus true capabilities in the type system. But not before the next couple of years. But maybe someone starts to clone this feature set early so they won't be a decade behind when Scala finally ships this… ;-))


Your links show several aspect of the WASM sandboxing techniques. Don't mixup the core WASM and WASI. The FS sandboxing is actually part of WASI, as core WASM doesn't allow any FS access or system calls.

> whitelist any and every call

This is the default WASM model. It provides no outside calls by default. This works fine for the original web browser model where WASM is essentially just providing a way to run a function from JS with near native speed. It's extremely limited in usefulness but fast and secure.

WASI is an effort to provide a set of curated APIs to make it easier to use WASM for more use cases like networking or even printing to a console.

> First of all you can forget about C/C++. Everything in this languages assumes free access to the system.

C/C++ works fine. It essentially acts like a bare metal embedded device, but without access to hardware registers. You cant even print to console by default.

This does means most of the C standard library won't work, but C itself doesn't care. There are no system calls either, only whitelisted functions calls statically provided to the WASM code. Again C/C++ don't care, but it means you can only use code that uses limited subset of the standard library.

The JVM's bytecode design makes it hard to translate C to it, whereas WASM is designed for languages like C with arbitrary pointer arithmetic. WASM just turns point access into memory offsets, while the JVM or CLR assume a Java like language.

> I don't find any such feature mentioned in the Wasmer docs. It seems completely without any sandbox!

Browsers have been shipping WASM VMs for years now without disaster, so apparently they do know whats required for sandboxing. If you can prove otherwise and break out of WASM you could make a lot of money from Google's security bounties or just selling it on the darknet. ;)

I'm sure theres been security flaws just like in any sandbox technology, but generally WASM appears successful. Its been adopted outside browsers by security conscious companies like cloud-flare and fastly to provide sandboxing of user code, etc.

> (To stress it once more: All VM languages are memory safe. That's not sandboxing. All the "sandboxed by default" claims are misleading, at least).

You're correct that limiting memory access is only part of what a sandbox requires. Memory safety is a crucial piece of sandboxing, though many VMs do provide that. However most VMs also provide mechanisms to escape the memory sandbox though so they're not good at being sandboxes.

The other crucial part for sandboxing is control flow. The VM must prevent code from being able to hijack control flow, or to otherwise generate code to escape the sandbox. The links you provided discuss how WASM does this currently:

> All control transfers—direct and indirect branches, as well as direct and indirect calls—are to known and type-checked destinations, so it's not possible to accidentally call into the middle of a function or branch outside of a function.

What most of the hype around WASM is actually about is the ability to provide this sandbox isolation after translating WASM bytecode to native binary code.

Most JVM VMs also do JIT'ing at runtime, but the JVM has some runtime features and assumptions that make statically compiling upfront harder. WASM was designed to enable ahead of time compiling from the outset. That is a key difference between JVM and WASM.

For example here's a paper from Stanford & UC folks for a static verification engine for checking that binary executables translated from WASM to maintain the sandboxing: https://cseweb.ucsd.edu//~dstefan/pubs/johnson:2021:veriwasm...

> One should never over promise on security! Java had to learn this the hard way over many years (as their sandbox had have holes in the past, and was also almost impossible to correctly configure).

To reiterate, WASM incorporated these details from the outset, to the point that providing useable WASM VMs outside of browsers years to come about.

If you're talking about WASI, you have a bit more of a point. WASI is the result of carefully adding back in things like FS access using capabilities and other techniques to keep it sandboxed. This is harder, and introduces more surface area to violate WASM's sandboxing. However WASI seems well thought out so far.


I really don’t want to sound argumentative just for the sake of it, but sandboxing through “not allowing any side effecting things” is quite.. trivial? Like, I have written a brainfuck interpreter and it can only do prints to stdout, so it is guaranteed safe, hell, it is quite good as a compile target!

There is nothing inherent in java bytecode that would make it unsafe, nor hard to AOT compile — runtime reflection is not part of the JVM spec itself, it is a separate API (akin to WASI) that provides this capability. So, a JVM interpreter can also do no harm without attaching the endpoints that can do harm obviously. Also, there used to be a project called gcj 20 years ago that managed to AOT compile java just fine, the only riddle here is the aforementioned reflection. Graal uses a closed-world assumption to solve it.

Your link is interesting though, will look into it.


> Your link is interesting though, will look into it.

Looks much like the byte-code verifier that is std. part of the JVM.

The foundations on which this is built look quite solid though.


### PART 1 (as the comment was too long for the system here) ###:

> The FS sandboxing is actually part of WASI

AFAIK it's part of some WASI implementations, and not a mandatory requirement by WASI.

But maybe I'm wrong here.

Could you point to some authoritative documents that bakes your claim about WASI?

> […] where WASM is essentially just providing a way to run a function from JS with near native speed.

Could you explain how you get "near native speed" in a managed VM? No VM overhead on WASM? What did all the other VMs wrong for so many years that everywhere else there are significant overheads and slowdowns compared to native code?

Could you point to some benchmarks that bake your claim?

> C/C++ works fine. It essentially acts like a bare metal embedded device, but without access to hardware registers. You cant even print to console by default.

Could you explain how some random C/C++ program can run in an environment without the possibility to do basically anything?

What happens for example when I print to the console form such program?

> This does means most of the C standard library won't work, but C itself doesn't care.

How does a C program run without C library?

I was never talking about the C/C++ languages as such.

I said: You can forget to cross compile C/C++. Because I assume that almost no code C/C++ code out there will work in an environment without any possibly to do basically anything.

But maybe I'm very wrong here. Could you explain how this works?

> There are no system calls either, only whitelisted functions calls statically provided to the WASM code.

Ah nice.

And those calls are automatically sandboxes, yes?

How is the sandbox configured?

How does it prevent anything bad form happening?

This would require call filters, that inspect the parameters, and then decide what to do on every call, right?

If so, what's about the overhead of such a "call firewall"? How does it affect performance?

Where do I find the documentation for this sandbox?

> The JVM's bytecode design makes it hard to translate C to it, whereas WASM is designed for languages like C with arbitrary pointer arithmetic. WASM just turns point access into memory offsets, while the JVM or CLR assume a Java like language.

How is this relevant?

If WASM is modeled after the C languages requirements, why are people saying that it would be easily usable for other, high-level languages?

Wouldn't that mean that I need to write a VM that runs in a VM?

How would such a construct affect performance and resource usage?

What additional sandboxing could this bring to the table?

Please keep in mind here that the VM in the VM needs to talk to the outside world to fulfill it's std. lib contracts. How does this work?

> Browsers have been shipping WASM VMs for years now without disaster, so apparently they do know whats required for sandboxing.

But we're not talking about an JS VM embedded WASM VM.

We're talking about a standalone WASM VM outside of the JS VM.

How does sandboxing work there? How are the WASI calls sandboxed? (See also all the remarks above).

Where can I find the documentation for that?

> If you can prove otherwise and break out of WASM you could make a lot of money from Google's security bounties or just selling it on the darknet. ;)

Could it be that you just again confused "sandboxing" with memory safety? (Which is, once again, a property every "managed" VM runtime provides).

> Its been adopted outside browsers by security conscious companies like cloud-flare and fastly to provide sandboxing of user code, etc.

Oh, more sandboxing.

Could you point to some documentation how this sandboxing works on the technical level?

AFAIK they just run the usual containers in HW hypervisor VMs, where you can than place your WASM runtime…

So you get in the end sandboxing form the std. hardware based VM. (Because nobody trusts containers for security. And then anyway, in such scenario the workload inside the container is irrelevant).

> Memory safety is a crucial piece of sandboxing, though many VMs do provide that.

Could you point to any VM that does not?

> However most VMs also provide mechanisms to escape the memory sandbox though so they're not good at being sandboxes.

How is WASI different here?

What's the magic that WASI has, but nobody else?

Do you think a sandbox like the one that the JVM just throw away could prevent memory access outside the JVM? How does the provided escape mechanism work actually on the JVM? Is this part of the JVM? Or would it require some "unsafe" access through unofficial APIs which are not part of the platform?

Could you explain how this looks like in other popular VMs? I'm not familiar with such.

> The other crucial part for sandboxing is control flow. The VM must prevent code from being able to hijack control flow, or to otherwise generate code to escape the sandbox.

Could you explain why this does not work reliably on the JVM? (Even there is by standard byte code verification in place, of course.)

But please keep in mind that there is no user-level way to generate native code on the fly on the JVM. Only a JIT, which is actually not part of the platform, can do this. So how do I hijack control flow on the JVM (or other popular VMs)? Could you explain this (under the assumption that there are no bugs in the implementation of course, as this would render any VM protections on any platform likely useless obviously).

> What most of the hype around WASM is actually about is the ability to provide this sandbox isolation after translating WASM bytecode to native binary code.

Even in the face of implementation bugs in the "translator"?

How does this magic work?

Why do they still add "bumper spaces" around the WASM memory then? Should be strictly unnecessary given the magic property of WASM that the AoT compiler or JIT output is still safe, or not?

> Most JVM VMs also do JIT'ing at runtime, but the JVM has some runtime features and assumptions that make statically compiling upfront harder. WASM was designed to enable ahead of time compiling from the outset. That is a key difference between JVM and WASM.

How would this work with say Java on WASM?

What's the magic here again that makes it hard to AoT compile Java for the the JVM platform but it's easy to compile it AoT to WASM? What do I miss?

Could it be that this feature is only relevant in case the language you're compiling is anyway one of the few that are AoT compiled and not run inside a VM by default?

But than again, how is WASM the superior VM to run all kinds of languages like advertised (given almost all languages besides a few exceptions are VM languages)?

> For example here's a paper from Stanford & UC folks for a static verification engine for checking that binary executables translated from WASM to maintain the sandboxing: https://cseweb.ucsd.edu//~dstefan/pubs/johnson:2021:veriwasm...

Interesting.

Is this VeriWasm widely used in industry? Who's using it in production?

(One could also ask who verified the verifier implementation, but that's always the question with SW verification; usually you can "just trust" multiple layers of insights. Otherwise SW verification would be useless; which it's not imho!)

At least the introduction of the paper answers a few of the previous questions. Let me cite:

> WebAssembly (Wasm) is a platform-independent bytecode that offers both good performance and runtime isolation. To implement isolation, the compiler inserts safety checks when it compiles Wasm to native machine code. While this approach is cheap, it also requires trust in the compiler’s correctness—trust that the compiler has inserted each necessary check, correctly formed, in each proper place. Unfortunately, subtle bugs in the Wasm compiler can break—and have broken isolation guarantees.

I'm not further commenting on this part. I think the statements stand on their own.


### PART 2 (as the comment was too long for the system here) ###:

> > One should never over promise on security! Java had to learn this the hard way over many years (as their sandbox had have holes in the past, and was also almost impossible to correctly configure).

> To reiterate, WASM incorporated these details from the outset, to the point that providing useable WASM VMs outside of browsers years to come about.

Could it be that you just again confused "sandboxing" and memory safety?

The problem with the JVM sandbox (and most of the time other VM languages) isn't memory safety!

There have been such bugs here and there, sure. In the JS VMs, the WASM WMs (like pointed out in the above linked paper), and also the JVMs.

But those bugs are the usual implementation bugs.

Once again, this is not relevant to the questions here. Memory safety is not a "sandbox"!

> WASI is the result of carefully adding back in things like FS access using capabilities and other techniques to keep it sandboxed.

What "sandbox" are you talking about?

There is only one WASI implementation that offers a extremely simple FS access filter. (And Wasmer, which we're taking about here, does not even have that, as I see it).

Capability security? Where is this implemented?

One again: I don't talk about what people dreamed up! I'm asking for the status quo.

> This is harder, and introduces more surface area to violate WASM's sandboxing.

Yes, that's the point.

Having a cage that does not let anything through is easy. Just build massive walls without windows and doors. Nothing can get out. Nothing can get in…

But such a cage is almost useless.

So the interesting part starts when a thing in the cage needs to talk to the outside world!

"Solving" the "trivial" problem is indeed easy.

Now show me how you solve the real problem!

But to my knowledge there is nothing there. Nothing. (Besides promises and cool sounding plans for some distant future).

> However WASI seems well thought out so far.

Yes, "thought out". But not implemented!

BTW: They did not come up with anything new here.

Capability security is at least around 40 years old.

The point is: Nobody ever implemented this outside of academia.

We have just now the first steps in that direction.

But that are at best beta versions of tech form the future…

As it stands today: WASM does not have any meaningful sandbox. (Memory safety is not a sandbox! It's "just" a prerequisite to be able to implement a sandbox. But it's not one by itself, and a feature _every_ VM runtime provides).

Even containers will give you more sandboxing based on the (by now) rich features of Linux namespaces. (Still nobody considers this a serous sandbox on which you could bet your ass. That's why we run containers in VM; because that's the only—more or less—reliable sandbox we currently have; as our OSes and hardware still don't provide capability security features).

---

Don't get me wrong though.

I do think that the whole "linear memory" idea for memory safety is indeed a very good one.

It's so good, I think this should be implemented on the HW level! (Or at least in a first step on the OS level).

But "really safe memory cages" aren't sandboxes.

Without capability security on top this does not provide any meaningful improvement over what we have already since decades.

But capability security isn't something that you can just to piggyback after the fact. Everything, form the languages used and their libs, up through the OS and VM layers need to be explicitly build with this mechanism in mind. We're still light years away form having such infrastructure!

But what the WASM people present is some fantasy world where all this is already in place.

Given how aggressive those obvious lies are pushed I can't come to any other conclusion than that there is a lot of bad faith behind this campaigns. "Someone" tries to push by all means their VM tech into the market. Even they're leaking around 20 years behind the next competitor. This whole thing is a disgusting marketing war.

And to be honest I'm quite scared how effective this ultra aggressive marketing is even it's almost completely based on highly over promised stuff up to, in its extreme, blatant lies. I hope the person I'm talking to here isn't part of this marketing effort. And people reading this start to ask themself the "right questions" finally ;-).


I do somewhat agree with the security aspects, though it seems to be in-process security measures are not the panacea.

> Overall JVM or CLR always seemed too heavyweight for many use cases.

The most common implementation may be; there are plenty of tiny jvms, some target embedded devices even.


Yeah, but then you run into the problem of, "are those tiny JVMs":

1. Well supported by a company and a community

2. Are they free?

Especially 2, it sounds ridiculous but frankly even huge corps just use free stuff whenever they can.


> […] jvms, some target embedded devices even.

Java was invented as IoT technology in the first place. Long before this acronym even existed.

It run on all the old 4-line monochrome text display dumb phones.

Java runs on SmartCards.


Yeah, I know, but those are not the most streamlined ways of using Java nowadays, that’s why I didn’t highlight these parts as much (also, smartcards only run java ME, which is a subset of SE)


Sure!

I wanted only to point out that using the word "even" in the cited part is kind of "funny". Because this was actually the originally intended usage of Java.

It was invented as safe replacement of C/C++ especially for embedded development. (But now, sure, it ended up on the really huge boxes in DCs).


Also most of them are also only support programming in Java. This always limited running arbitrary C code, or other languages like C++, Go, Nim, Rust, etc.


The JVM is Turing complete. So you can run any language you please on it.

The question is—as always—how efficient this is.

But this goes also the other way around.

Even you can in theory run arbitrary languages on a WASM runtime the question how efficient this is stands also!

And in fact running anything else than "C languages" in WASM is at least as inefficient as running "C languages" on the JVM…


> And in fact running anything else than "C languages" in WASM is at least as inefficient as running "C languages" on the JVM…

Hell, it is a really safe bet to say that running a C-like program on the JVM is much much faster than porting a whole runtime (which is very performance-oriented) on top of a runtime and make it run some code. Wasm simply can’t expose the optimizations runtimes routinely make use of (template interpreters for example))


If I compile a C or Rust program to run in GraalVM, will the LLVM bitcode be converted to some sort of universal bytecode, or does Graal attempt to run the bitcode directly via a plugin? (e.g. do I distribute GraalVM bytecode or LLVM bitcode to the user?).

The documentation is a bit unclear about this, but there's this weird blurb at the end:

> Note: LLVM bitcode is platform-dependent. The program must be compiled to bitcode for an appropriate platform.

...why would this detail even matter if LLVM bitcode is converted to 'GraalVM bytecode'? In any case, it doesn't sound much like "write once run everywhere" ;)

See: https://www.graalvm.org/22.2/reference-manual/llvm/


Graal’s truffle runtime works basically as an AST interpreter, so you have to ship the LLVM bitcode.

I have yet to get my feet wet with sulong, but my guess would be that LLVM will produce different bitcode on different platforms, and thus the execution can potentially be different - also note that llvm bitcode is not a stable format. But I don’t think that interpreting it on a different platform than it was compiled on would have a fundamental reason not to work (after all, it is just java code) - perhaps it uses the platform llvm libs for some parsing, which is not platform-agnostic?


Hilarious that you mention it, because Graal has a Wasm front end.

https://www.graalvm.org/22.1/reference-manual/wasm/


I suppose the "novelty" is the existence of compilation to WASM target in more and more compiler toolchains, so you can use things. Though to your point GraalVM work is also progressing a lot! Nice to have a lot of energy in this space in general


> I suppose the "novelty" is the existence of compilation to WASM target in more and more compiler toolchains

Which ones?

AFAIK WSAM runs only "C-like" language properly.

Everything else is a major hack and slow as hell.

When it even exists of course. Because to my knowledge there aren't much languages that compile to WASM besides C/C++/Rust. Because WASM lacks features for VM languages (and that is the big majority of languages). Did something in this regard change lately?


I wasn't being careful with my language. But we're basically looking at a continuation of the Emscriptem "hack" with WASM, meaning that you can run CPython in the browser and have a lot of third party pacakges work (much better than GraalVM's "PoC" Python interpreter).

And yeah, I guess we're able to run things in the browser with WASM. One could say "well why use it on a machine outside the browser", to which I reply the obvious thing: hell of a lot easier to just use one VM rather than two.

I think there are also social dynamics at play when it comes to _anything_ related to Oracle, which does poison the well. It's unfair to the GraalVM people's serious work, but it is what it is.


There are plenty languages with WASM support that aren't "C-like" in this list (and you don't need special "GC support" in WASM to implement a GC in WebAssembly, at the cost of bundling the GC implementation in your WASM blob)

https://github.com/appcypher/awesome-wasm-langs


> There are plenty languages with WASM support that aren't "C-like" in this list

Really? I see marked as "production ready" (whatever this means in this case):

  AssemblyScript
  Brainfuck
  C
  C++
  Go
  Forth
  Zig
  Rust
  COBOL
  C#
  F#
  Lua
  Clean
  Lobster
  TypeScript
  Never
So the realistic options are: C/C++, Go, Zig, Rust, C#/F#, and Lua.

Where C#/F# is slow as hell, with a gigantic overhead.

Lua is likely slow (don't know for sure).

The rest looks pretty much like "the C languages" to me.

> […] and you don't need special "GC support" in WASM to implement a GC in WebAssembly, at the cost […]

Oh, someone is prepared.

Sure, you can build such thing. One can also build a Web-Browser in Brainfuck; somehow (and than even run it in a WASM container).

The point is that that's extremely inefficient.

In the browser it does even make less sense as there is the JS VM with a pretty solid GC right next to the WASM runtime.

So compiling a VM language to WASM is already questionable in itself. But without proper low-level building blocks to implement managed language runtimes efficiently this can be hardly even called working. Just have a look how for example Blazor compares to native JS (which people consider slow and sluggish already):

https://krausest.github.io/js-framework-benchmark/2022/table...


> The point is that that's extremely inefficient.

We're talking about garbage collection though, this will always be inefficient, doesn't matter much on which side of the fence it is implemented. At best you can save some WASM download size by piggybacking on the Javascript engine's garbage collector (that's essentially what the WASM GC proposal is about).


> We're talking about garbage collection though, this will always be inefficient, doesn't matter much on which side of the fence it is implemented.

No, that's just not true.

You can't implement GC in WASM currently in any sane way.

As already said more than once here: WASM is lacking needed features. (For example memory fence instructions).

Any GC build in WASM will be extremely slow and inefficient. It will be also a stop-the-world GC. Because you can't build anything else.

GC implemented in WASM is at the moment completely impracticable.

Sure, you "can" do it still. But that's like building a banking application in Brainfuck. You can do that. In theory. Maybe even someone did it "for real". All this does not matter. It's brainfuck.

And that's not only the GC.

VM runtimes, and JITs need some more features to be implemented efficiently.

WASM is also lacking those features (like computed go-to).

Bottom line is: It's impossible to implement a VM in the WASM VM even remotely acceptable.

This is also backed by data:

I've showed already the catastrophic performance of Blazor. (And this is something where millions of dollars went for years to make it even "work".)


> We're talking about garbage collection though, this will always be inefficient

Come on, it is a ridiculous claim. GCs can run completely concurrently with the actual code with barely any coordination between the runtime and the running code - they basically make allocation’s and deallocation’s costs asymptotically zero. You do not believe that manual allocations are free, right?


The whole point of explicit memory management is to avoid memory allocation and deallocation calls in the first place (by controlling where and when allocation/deallocation exactly happens, and that should not be anywhere near a hot code path). And with that, allocator performance doesn't really matter anymore (that's also why 'fast' memory allocators like mimalloc or jemalloc are really kinda pointless, if those make a measurable performance difference, than the code is already calling the alloc/free functions way too often.


> explicit memory management is to avoid memory allocation and deallocation calls in the first place

No, it isn’t. Memory management.

Also, so you want to write code with hardcoded sizes for everything or what? Yeah, I surely want programs that die on a string of length 35 because only 32 were allocated upfront.

Also, managed languages can have hot loops without any allocation going on, you know right?


You really need to spend a bit of time to educate yourself and tinker a bit with manual memory management (there's a bit more to it than just calling malloc/free each time you need to grab 35 bytes of memory).


Thank you very much, I’m quite familiar with it. As are professionals who write those GC systems we are talking about, probably much much more so than any of us.


Basically what IBM and Unisys mainframes have been doing the last 60 years.


Unfortunately none of my users run IBM or Unisys mainframes (as far as I'm aware at least).


What about Windows/Linux/macOS with CLR, or Android with ART?


The task would involve compiling three big and complex C++ libraries (that have no equivalent in other languages) to the respective bytecode formats, and my past experiments (from the time before Emscripten was a thing) were not very successful. Maybe that has improved in the meantime, maybe not.

Nothing beats clang's wasm output in that regard (e.g. both Emscripten's 'emcc' and Zig's 'zig cc' are drop-in replacements for a GCC-like toolchain which can produce WASM).


C++/CLI supports C++17...


But AFAIK that's only supported by the MSVC toolchain which in turn only runs on Windows (and I tried too often running MSVC on non-Windows operating systems via Wine, even if it works, the process there it's a mess).


But you could run the JVM. Which does the same thing also since decades.

The difference is: The JVM is already proven in production since a very long time.


JVM has it's own object model (which doesn't even have value type support when defining memory layouts), GC, etc. Bad level of abstraction for low level language target (although it has been tried many times).

Not to mention runtime is anything but lightweight and easily embeddable.


"NestedVM provides binary translation for Java Bytecode. This is done by having GCC compile to a MIPS binary which is then translated to a Java class file. Hence any application written in C, C++, Fortran, or any other language supported by GCC can be run in 100% pure Java with no source changes."

http://nestedvm.ibex.org/


I know - I've seen other tech like this, "nobody" uses it for a reason.


I mean, you just create an array of longs and that’s it? That’s pretty much what wasm does as well.

> Not to mention runtime is anything but lightweight and easily embeddable

There are more JVM implementations than Wasm ones, I’m sure there are plenty small, embeddable one. But arguably the best would have been a single, performant JVM built into the browser instead of the JS engine, allowing for both scripted usage and this “sandboxed compile target” one. (Applets failed more due to politics, than anything)


It's also valuable for running code written in <random language> to be executed in <another random language>.

Write a library in Rust and compile it to WASM, theoretically any language with WASM bindings could run it.

This could really make niche languages more easily adopted if their execution environment supported libraries in WASM.

Imagine using Java's JDBC from something like Nim. Nim could take advantage of a 30 year old mature and fast database access framework without haveing to envest that ime and effort themselves.

Or even something more modern like the polars dataframe library.


Firefox uses this approach to create a lightweight, in-process sandbox (called "RLBox") for some third-party libraries. The library is compiled from C/C++ to wasm and then wasm is transpiled back to C++, all at Firefox compile time so no wasm compilation is needed at Firefox run time.

https://hacks.mozilla.org/2021/12/webassembly-and-back-again...


> Write a library in Rust and compile it to WASM

this misses the fact that (unless I'm wrong), WASM by itself can't really do anything like file system/network operations

I know that's not the main usecase of where to put WASM logic that needs to be performant (it's the opposite really)

I just think it's worth calling out that a WASM library really can't do much from what I understand. Like... basic math? You have to supply it (through a WASM runtime) interop to other functions it can call... I think?

Would love to be taught/proven wrong.


This is where WASI (WebAssembly System Interface) comes in.


But isn't WASI considered harmful?

I absolutely disagree with ASC's stance on this, but it seems that the AssemblyScript project at least wants nothing to do with that kind of thing:

[1] https://devclass.com/2022/09/08/assemblyscript-project-wasi-...

[2] https://www.assemblyscript.org/standards-objections.html

[3] https://github.com/WebAssembly/WASI/issues/401


I have a hard time taking this seriously, it's the objections of one individual who seems to be seeing ulterior motives behind WASI... I don't think their objections are really as strong as they make out. Big red "In violation" labels are a bit much.

WASI is trying to be a cross language API for use by multiple languages that target WASM. But the author wants this API to more closely follow existing JS conventions? Sure that's useful to JS/Web, but it's not useful for anyone else trying to target WASM with a language that's not JS. And if you want to target Web API's with JS, can't you already just write native JS?

Bikeshedding over string encoding for example and objecting to WASI's promotion of UTF-8 because it doesn't match the encoding used by JS.


Let me ask you this. All nonsense aside about like... standard discussion and what not.

Say I write a Rust program to use `reqwest` to make a HTTP request to some API that is going to return me JSON.

I can compile it to... ELF with Rust I guess on Linux, or I can use Rust to compile it to:

> wasm32-wasi - when using wasmtime this is likely what you'll be using. The WASI target is integrated into the standard library and is intended on producing standalone binaries.

> wasm32-unknown-unknown - this target, like the WASI one, is focused on producing single .wasm binaries. The standard library, however, is largely stubbed out since the "unknown" part of the target means libstd can't assume anything. This means that while binaries will likely work in wasmtime, common conveniences like println! or panic! won't work.

> wasm32-unknown-emscripten - this target is intended to work in a web browser and produces a .wasm file coupled with a *.js file, and it is not compatible with wasmtime.

Say the Tokio async runtime works for wasm32-wasi (I don't think it does currently, I could be wrong) and reqwest + all of its network dependencies compile to wasm32-wasi (not sure if they do, I think there is progress) and say lite-json or some kind of JSON de-serizaliation works

Why would I compile + run as wasm32-wasi instead of stable-x86_64-unknown-linux-gnu?

Interesting links:

https://github.com/tokio-rs/tokio/issues/4827 - tokio support

https://github.com/async-rs/async-std/issues/505 - async-std support

https://www.reddit.com/r/rust/comments/h9bakg/could_not_find... - > There's no blocking implementation available for WASM. The WASM backend uses HTML APIs (fetch) and is supposed to run in a browser, where you can't block the event loop


It's my understanding that WASI is using Unix-like abstractions, because they also target native execution, while the AssemblyScript would prefer web-like abstractions, because they exclusively target the browser. From your second link at least, this seems like the main technical complaint:

> Languages that would naturally fit the Web platform not only are overlooked, but WASI's self-imposed abstinence of Web concepts undermines other languages' interoperability potential with JS and the Web platform specifically.

The problem is that objectively, the web platform is garbage. Half-baked, weirdly incomplete abstractions, most of can only be rationally explained as either historical accidents or the aftermath of political fights on standards committees. Why would anyone base a new abstraction around those if they don't strictly have to?


Considered harmful by whom?

After looking at the objections from these guys, they seem to boil down to, "but it makes non-web development more viable again, and that's bad for the web". The first part is true. The second part is arguable, but IMO if it is true, then balance needs to be restored.


More like dcodeIO and his AssemblyScript ambitions are considered harmful to us not having to live with the legacy hacks. The sad part is that it seems they have won, and the standard will be uglified on the fundamental level: https://github.com/WebAssembly/stringref/blob/main/proposals... Now the time came for WASI to submit, hence the "fatwa".


> But isn't WASI considered harmful?

Lmao. The guy is just mad that WASI uses utf-8, as opposed to utf-16 (which is what Javascript uses)


https://www.npmjs.com/package/as-fetch

this has 7 weekly downloads... I would expect more?


The as-fetch readme says undici is faster (which is the implementation of fetch that shipped in Node.js 18).

So 7 weekly downloads sounds about right for an unknown package that is slower.


> Imagine using Java's JDBC from something like Nim.

You can already do this with JNI. How does WASM improve things? In both cases (WASM or native code) you get the overhead of two runtimes and the hassle of converting data types, don't you?


WASM is executable from every language to every language, you wouldn't have to write code specifically targeting the JNI for example. Say you want to use a PDF library from Java, a web server from C# and some scripts someone wrote in Python, and for whatever reason your preferred language of the day is Haskell. In the normal case you'd have to rely on someone to maintain Java -> Haskell, C# -> Haskell and Python -> Haskell glue code. But with wasm, you just pull in csharp.wasm, python.wasm and java.wasm, so it's just one binding layer, not three.

It's often the case that people choose languages based on the availability of the libraries written in those languages. The goal of non-browser WASM is to get rid of that and to minimize the friction of inter-language communication, so you don't have to rewrite it in $language. WASM is not tied to any language (like the JNI).


> But with wasm, you just pull in csharp.wasm, python.wasm and java.wasm, so it's just one binding layer, not three.

A bit of a rant, but there's nothing specific to WebAssembly about this.

Whether you're using WebAssembly or native code:

- The basic interface you get between caller and callee is a low-level calling convention, where essentially all you have are integers (which can be pointers), and any higher-level data structures need to be built out of that.

- A slightly higher-level interface is the C ABI; many languages support exporting and consuming APIs using the C ABI, but it can be frustratingly low-level.

- To provide an even higher-level interface, there are bindings generators, which could in principle either be designed as direct language-to-language bridges, or as a single common standard that any language can provide and consume APIs for.

The WebAssembly Component Model standard and the wit-bindgen tool are an example of the latter. They happen to be defined specifically for WebAssembly rather than generically for any architecture. If they become ubiquitous at some point in the future like they're supposed to, then WebAssembly will have an advantage when it comes to high-level bindings, not because of any fundamental technical aspect of WebAssembly itself, but just because people building these bindings on top of WebAssembly have more motivation and more consensus. (WebAssembly does have a technical advantage when it comes to sandboxing between components, but this is relatively unimportant for most use cases.)

But for now, wit-bindgen isn't ubiquitous, and most of those languages don't even work in WebAssembly yet…


I work on wit-bindgen. One major advantage of the WebAssembly VM is that we can trust the call stack, which gives cross-language calls optimization opportunities to skip serializarion or copies. This will be an even more important when we add async to the component model, and e.g. async rust can await on async typescript, all in the same “executor” in Rust terms.

Sandboxing also goes a long way towards containing the supply chain security issues that every language is susceptible to.


What do you mean by ‘trust the call stack’? Do you mean trusting that a function you call won’t longjmp out or otherwise break out of the call without returning? (Plenty of native code already assumes that functions it calls won’t do that.) Or something else?


Wasm doesn’t yet have any sort of longjmp instructions. Stack switching is currently a proposal and the leading candidate is based on delimited continuations. Additionally, there are no wasm instructions that can manipulate the control stack besides call, indirect call, and return, which are always typechecked. So, if you call untrusted code, you can be assured that it will not be able to manipulate your stack and that it will either return or trap.

Native code might assume that code it calls won’t misbehave in these ways, but wasm guarantees it, and that allows wasm VMs which run untrusted code to have more efficient implementations.


> A slightly higher-level interface is the C ABI;

Small remark: There is nothing like "the C ABI".

https://faultlore.com/blah/c-isnt-a-language/#c-doesnt-actua...


you wouldn't have to write code specifically targeting the JNI for example

Why not? You still need operations like "create object", "look up method", "invoke method", "convert type between languages" etc. WASM doesn't have any kind of polyglot layer that does this automatically.

Ironically, Graal/Truffle actually do. There's a whole infrastructure where languages can expose their structures, functions, objects etc via a language-neutral in-process protocol and the compiler understands how to optimize across the transitions, so you can actually load JavaScript into Python and do those sorts of things:

https://www.graalvm.org/latest/reference-manual/polyglot-pro...

The API you use to import code from other languages is standardized, so it doesn't matter what language the other side is using. But WASM doesn't do anything like that.

"with wasm, you just pull in csharp.wasm, python.wasm and java.wasm, so it's just one binding layer, not three"

Are these real files/projects you're talking about here? If so, can you show us these things? Because WASM seems far too low level to define a Truffle-like polyglot layer let alone make it fast.


That does look pretty awesome - wouldn't it hurt the performance tho? Especially with the DB Example, a database usually needs to be fast.


In the short term, you wouldn't want to run databases in WASM. You could, but it's not really worth the effort, as long as the WASM runtime allows TCP connections, you can just connect to any hosted DB as usual.

For performance, we ship three compiler backends: LLVM (fast execution, but slowest compilation), cranelift and singlepass (our own compiler, very fast compilation and you can compile untrusted code - but slowest execution). There is a slowdown, but the goal is to keep that at a minimum (proper performance tracking is on the bucket list). We are pre-compiling the python.wasm (which was already pre-optimized when the compilation to WASM happened) with LLVM, so you should get assembly that is very close to the native execution, with the exception of the necessary VM overhead. The goal is to make it so that the interoperability gains are worth the performance hit.


Sure, maybe it's not as fast to execute as another implementation, but having ANY implementation is far more useful than none at all.

Here's an example where performance wouldn't matter as much:

Let's say I'm the author of a programming language and I want to add a db layer to my standard lib.

Via WASM I can use a working backend while I'm protyping the API for my db layer. If the performance isn't fast enough I can start implementing my own "native" version with feature parity.

I can then use some of the tests from the original library (via WASM) to make sure my implementation has feature parity to the original.


How would you do that? Could you please show a working example?

What you're saying is completely impossible right now AFIK…


Even if the feature set were limited to what’s possible with Java/JNI, the fact that Oracle does not own any piece of it is a feature in its own right.


Dead horse. Google has more control everything web related (including wasm) than oracle does over Java.


GraalVM’s polyglot execution does solve this problem, it can even optimize across language barriers. (But it runs native languages as LLVM “bitcode” basically, not natively)


GraalVM will Not succeed, because every language needs Tour be reimplemented in graal, in wasm every language just needs a wasm Target. Also Java is really slow Boy adding a wasm Target. Most languages have a way to run on a wasm engine.


They have to be implemented as interpreters only though.

> Most languages have a way to run on a wasm engine

But it is basically useless for managed languages that as of yet has to bring their runtimes as well.


It's not useless, it's just a lower layer in the stack. Decoupling high-level managed runtimes from underlying low-level bytecode makes a lot of sense. Delivery is another question, and we'll probably solve that by caching common runtimes.


I'm not sure if it's mainstream but my thoughts on server-side WASM always run to user-provided logic. WASM provides a helpful building block for a generic user-provided logic sandboxed runtime.

Think about a workflow engine embedded in a marketing product. Usually there's some kind of GUI builder which generates an AST to be interpreted directly at runtime. What if instead the GUI generated a WASM artifact to be run on sandboxed runtimes?

What if, furthermore, you offered advanced users the opportunity to upload WASM binaries where they could implement arbitrarily complex logic to be executed in the sandbox?

I think this is a super powerful concept, although of course making a business case for implementing it is the trick.


I don't think a server-side sandbox makes sense for anything that is JIT-based (or even binary translation). We already have KVM which is actual native performance, and it can run anything you would ever want, and then some. WASM is bytecode working on a 2GB linear arena, and it fits OK in a browser.


I don't think that's really the use case I'm describing. Maybe I'm doing a bad job, I dunno.

The use case is essentially user logic for event stream processing, where the events are things like "received an email" or "clicked a link" or "3 days have passed". You're not going to spin up a KVM for every contact on a 2 million member email list even if you're using Firecracker, but executing a WASM blob for every event might be feasible.


The 2GB limit was a temporary browser limitation. Modern browers mostly support 4GB now. And wasm64 is testable today, which supports 64-bit pointers and more than 4GB.


Being able to add arbitrary logic to an otherwise static binary has a lot of interesting use cases. For example Envoy Proxy supports hot-loading arbitrary HTTP filters compiled to WASM into its filter-chain. This allows users to extend the feature set of Envoy, by adding custom logic to request parsing, reporting custom metrics, calling out to other services before forwarding the request, etc etc.

This allows their unique custom use-case-specific code to be managed separately to Envoy, so it can be ported across upgrades etc. It also means that if there's a very particular feature you want that's unique to your business, and wouldn't make sense to contribute to the upstream OSS project, you can write a WASM module for it.

It's somewhat niche, because anything built in this way which is generally useful to many users, will probably just be made a native feature of the host platform. Conversely, anything that does something significantly complex and custom should probably live as it's own stand-alone microservice somewhere. There's still a lot of room for value between the two extremes though!


- Running code on a server you don't control

- Running code you don't fully trust on a server you do control

WASM comes with powerful sandboxing, and if you combine that with static linking you can pretty much drop Docker for your PaaS (and all the overhead/complexity/insecurity that comes with it). This is what Cloudflare Workers do


WASM has an OS abstraction API that ends up being pretty good. There's work in progress on cross language resource sharing, interface types, etc. It's early days yet but this is generating excitement for WASM as a sort of very lightweight cross language container/vm.

It's also useful in "plugin" scenarios, like say filtering code in a network proxy. Or if you wanted to make your own Function as a Service system.


It lets you run untrusted code. Great for exposing a plugin API.


And can someone ELI5 why WebAssembly is useful, given that there are already a myriad of other virtual machines out there (JVM, CLR, BEAM, etc)?

And why could/did those other virtual machines not evolve to fulfill the need that WebAssembly fulfills? Why is a new machine language and new virtual machine necessary?


>And why could/did those other virtual machines not evolve to fulfill the need that WebAssembly fulfills?

All three were designed primarily as bytecode interpeters that would run as a layer between the OS and application, and were primarily designed to run stand-alone (i.e. desktop/server apps). Java was originally included in most web browsers, but the applet model just didn't get it done for users - and most Java software moved either be web applications (i.e. serving HTML) or desktop or mobile applications.

> Why is a new machine language and new virtual machine necessary?

WASM was designed to be embedable (and secure), streamable and is now ubiquitous as it is supported by all three major browsers, plus Node (and Deno) and many desktop web-app platforms (e.g. Electron). The embedable part is what makes it really different than JVM, CLR and BEAM - for example, you can include a WASM runtime in your application and call WASM code from a C or Rust app just like the browser does.


Better educate yourself on the CLR, not only was it designed for multiple languages, including C++, it doesn't support interpeters, only AOT and JIT compilation.


Never made that claim. You are an expert on both CLR and JVM... what is your take on WASM?


It should stay in the browser, and is the political outcome of Mozilla not adopting PNaCL, which is kind of ironinc given how they are now struggling with 3% market share.

Had it been today, Google would have been able to push PNaCL no matter what.

> One of the exciting things in Visual Studio .NET is its language agnosticism. If a vendor has written a .NET-compliant language, you can use it in Visual Studio .NET. It'll work just as well as C# or C++ or Visual Basic. This isn't just a future feature-in-planning. There are already nearly two dozen languages being developed for Visual Studio .NET: Visual Basic, C#, C++, JScript, APL, Cobol, Eiffel, Fortran, Pascal, Perl, Python, RPG, Smalltalk, Oberon, Component Pascal, Haskell/Mondrian, Scheme, Mercury, Alice, and even the Java language.

-- February 2002 issue of MSDN Magazine

https://learn.microsoft.com/en-us/archive/msdn-magazine/2002...

As for the JVM, it is kind of ironic as well, that after bashing Java Application Servers, there are startups trying to replicate them using a mix of Docker containers, Kubernetes and WASM.

So they aren't that bad after all.


It's kind of entertaining watching the same set of ideas be tried in different ways over the years.


In a real sense, WASM isn't a new VM. It's an evolution of Javascript, via asm.js, so it builds on the sandboxing that browsers need for JS.

As part of that, it really doesn't do very much. Other more general purpose VMs first let you do things. This has implications for running untrusted code: the JVM has never _quite_ managed to lock things down, and has a model where we restrict code that would otherwise have access (via reflection) to a lot of things we don't want it to have access to.

WASM starts with a bounded set of "RAM" and the ability to define code that runs on a "CPU". There's no mechanism for the CPU to access anything outside of the data it's been explicitly allocated. That makes it more difficult to actually do anything, but also more difficult for malicious code to do anything it shouldn't.

With much stricter invariants comes the ability to statically validate the invariants, too. Which is where projects like Mozilla's use of WASM as an intermediate format that's then converted to C are really interesting: correctly written C will maintain these invariants too, but we can't validate them directly. We can validate the invariants in WASM then maintain them by construction as we convert to C and onwards to native code.


Webassembly can be targeted by C/C++ and Rust. It's also designed with security in mind. The JVM is not a reliable sandbox.


JVM also can be targeted by C/C++ and Rust. In fact NestedVM was published in 2004... I concede WebAssembly does sandboxing better.


There's also the fact that the JVM is huge (~160MB download) but a WASM runtime is like 4MB.


The main thing is that browser makers can implement it on top of their existing JS engines at relatively low cost, and the language model is basically just C so there's no difficult consensus building. In other words it's expedient for the browser guys, given that Mozilla killed all prior attempts to do things like NaCL, there was also an earlier initiative to teach V8 how to run JVM bytecode that got killed off by the same problem. Mozilla just systematically killed off any attempt to non-JS stuff. WASM sort of snuck in via the backdoor using hacks like Emscripten and asm.js and Firefox was losing market share, so WASM is what we ended up with.

Outside the browser as the other comments say it's about sandboxing primarily, and the feeling that it's not too dependent on a single vendor. Of course that means not much useful code runs inside WASM. The hard bit about sandboxing is not actually doing it, so much as allowing a usefully flexible set of permissions and features for sandboxed code.

Interestingly, Graal is also developing a sandbox. And with native-image you can compile the language implementations down to native code. So you could soon (even today actually but it's not really advertised) load a sandboxing JS or Python or Ruby or indeed WASM implementation from a shared library using a simple C API. Again though the hard part is actually that "real" code tends to have extensive OS dependencies. The JS ecosystem finds wide usage partly because so many modules are written for the browser which allows very little, whereas in the Python/Java/etc ecosystems modules frequently will assume things like filesystem access.


WASM is basically a misnomer at this point. People are using it as a universal virtual machine/runtime. Whether that makes any sense is still an open question.


An example of this is Microsoft Flight Simulator. Packages such as aircraft are distributed/compiled as WASM modules and run (as I understand it) in a sandboxed environment within the simulator.


That’s the first use case that’s practical, in the wild, and adopted by Microsoft nonetheless.

Do you have any additional details/links on how this works?


From my limited understanding it’s actually the aircraft instruments that run JS/WASM .

https://docs.flightsimulator.com/html/Programming_Tools/WASM...


> WASM is basically a misnomer at this point.

Web standards/technologies are in wide use outside of browsers (via things like Electron), so you may find that the name makes more sense when viewed through that lens.


In your view, why does it not make sense? It certainly seems appealing as a universal runtime, and lives up to its claims as long as things like WASI get standardized.


It doesn't make much sense because if you want a universal runtime, JVM is a better choice.


That very much depends on what you need a runtime for. JVM bytecode semantics are not a good match for something like C++ or Rust.


Plugins for desktop apps would be safer if the plugin is run with WASM.


WASM is JVM with lessons learned


What lessons did it learn?


How to implement a safe sandbox.


That remains to be battle tested, and there are already some USENIX talks on the matter.


Sticking it in every modern web browser for the past several years is a pretty good way of battle testing it!


Except this isn't a browser, and a bytecode paper standard isn't an implementation.


Well, if you rephrase that slightly, it probably covers the main idea:

> How to implement a safe<<R>> sandbox.


I think it’s meant to make it easier to use. They also have their whole package manager to use


"dumb clients" don't exist anymore. Why run things on the server and have to deal with scaling issues, if I can just distribute super complex applications easily and as reliably as publishing a web page?


Next.js' (and others') server side rendering exists and React Server Components exist as well. We're seeing a reversion back to the server due to SEO and performance concerns.


Your example is about something that gives power to the developers. My is about something that gives power to application users.

Which do you think is more important for non-developers?


Whatever get their job done faster. Don't host an ecommerce site as a client-side app, no one will buy your products if they don't show up on Google. Same with heavy websites, people complain often of bloated JS-based sites hogging their CPU, RAM and battery life. Doing the computation on the server is actually beneficial to the user's hardware. Non-developers don't care about client-side computing as much developers think they do.

Aside, I also can't believe I'm defending server side rendering in this day and age where people actually think client side routing is better. Around 10 years ago when React was still getting new, I would have held the same views as you. It's interesting how tech moves cyclically.


I don't think we are contradicting each other. I am not talking about using WASM to make a ecommerce site, or any site for that matter. I am talking about applications running in the browser. Games. Email/Social media clients. Productivity Tools. Media Players. Basically anything that people want to do on a mobile app, but that could be done/distributed via the browser.


VC money searching out the next gold mine for re-inventing P-Code, IBM TIMI, Burroughs, M-Code, EM intermediate language, JVM bytecode, MSIL, ....


Is it really that well-funded? I doubt there's much money in P-Code v2 - most devs see right through it.


So much that is where Docker is trying to pivot into, WASM containers.


Yeah, but what's the business angle to sell to VCs?

Putting ads in the low level runtime? :-))))


Java Application Servers reboot.


wasm is a specification for a VM (VM as in Java, not as in AWS/docker).

wasm gives you the bare minimum to run, other projects fill the gaps between that and what you would normally expect for an execution environment (ABIs, file system access, stacks, etc...). wasmer is one of such projects.


Can this be compared to something like αcτµαlly pδrταblε εxεcµταblε [1], that makes a single executable run on Linux, MacOS, Windows, FreeBSD, OpenBSD, and NetBSD?

While wasmer seems to support more source languages, it requires running the executable under a WASM virtual machine. Are there other important differences?

[1] https://justine.lol/ape.html


WASM also gives you sandboxing


And it works the same regardless of the host CPU architecture, whereas APE is built around x86_64.


There's another blog post by Wasmer where they compare with ape/cosmopolitan.

> How is this approach different? ape is aiming to create one standalone binary that works everywhere (same chipset, x86 as lingua franca). On the other hand, Wasmer aims to have one standalone lingua franca (Wasm), that can target multiple OSes (macOS, Linux, Windows), chipsets (x86, ARM, RISC-V) and programming languages (Python, Rust, Go…).

> On one hand, both ape and Wasmer rely on a “universal binary interface” to interact universally with the Operating System: Cosmopolitan (as a universal libc POSIX interface) in the case of ape, and WASI in the case of Wasmer.

> On the other hand, since Wasmer relies on WASI it can also offer a full-sandboxed execution when running the binary (this means that by default no files or sockets could be accessed or created by the binary unless explicitly allowed, for example).

WebAssembly as a Universal Binary Format (Part II: WAPM) - Portable Executables - https://wasmer.io/posts/wasm-as-universal-binary-format-part...


Running WASM outside of a web browser? Obligatory Gary Bernhardt, “The Birth and Death of JavaScript”: https://www.destroyallsoftware.com/talks/the-birth-and-death...


Javascript and WASM are unrelated


The parent comment didn't say they are. It's a very well known talk in which the speaker describes a hypothetical future technology that looks a lot like WASM.


Are they? Wasm is just asm.js turned into an independent thing.


The docs.wasmer.io page could use some work (it looks nice, though!) For instance, under the C/C++ section, the MinGW link at the bottom leads to a hijacked domain, and the "Wasmer C API" link in the sidebar leads to a 404.


I have a use case in mind

I have a piece of library written in rust that i need to run on multiple different hosting environment due to business reasons, like java/js. They will all call this library to validate part of the logic at the same time do something else

Could wasmer help in this case for me to write once and have consistent behavior everywhere ?


Yes.


The `create-exe` subcommand is interesting!

For any language with decent cross compiling capability, is there a use case for `create-exe`? Eg i use Rust these days.. and i wonder if there's any use case for me to cross compile via wasmer instead of natively. My project(s) do work on WASM as a target (for browser reasons), maybe it would be easier to setup cross compiling via wasmer and not manage the release pipelines i have?

Though for some of my performance critical applications i may not want to bother with it. Simply because i'd suspect wasmer might not have the same platform specific optimizations that natively compiling would give me.


Wasm provides very extensive sandboxing capabilities that are extremely valuable for certain applications (plugins, real-time collaboration, multi tenant hosting), and pointless for others. You can leverage that by using wasm and create-exe.


Im a bit confused with the WASM landscape. It seems there are numerous implementations of the runtime. How do I go about finding WHICH runtime is best for my needs? Is there a list of them available somewhere?


It depends on your needs. This awesome wasm list also is confusing. https://github.com/appcypher/awesome-wasm-runtimes


Many thanks. Ill dig through them and see what I can find


While I'm glad to see WASM get more attention, iirc wasmer has had some behavioral issues / drama in the past.

However, it seems they're making far more progress than wasmtime, so taking the bad with the good I guess.


That progress is mostly boilerplate. For instance if you want a memory filesystem, you probably want a dedicated filesystem module with features like an overlay filesystem. If you want an executable, you can just add it to your build scripts.


One annoyance, on the wapm website, seems you can't click on search results to open in a new tab. :-/

Wasmer seems pretty cool, and may in fact be a future for micro-services.


Off topic but is there a good way of running wasi on browser?


There are multiple ways! I'd recommend `@wasmer/wasi` since it uses the same WASI implementation as Wasmer (compiled from Rust to Wasm using wasm-bindgen):

https://www.npmjs.com/package/@wasmer/wasi


wasi-js is another one I’m actively supporting that is in pure JavaScript (hence small and easily hackable): https://www.npmjs.com/package/wasi-js

This is based on what wasmer used to provide for wasi in the browser before they did their major rewrite in rust mentioned above. I personally find the JavaScript version more useful for my projects so I revived their old project and am maintaining it.


Thanks for this info! I have a terminal on my website that was still using the old version and I've been wanting to upgrade it and get better input/blocking support. I will give this a try.


I have added some new ad hoc hooks for blocking io. You can see how they are used in https://CoWasm.org and https://CoWasm.sh


I started digging into it, looks promising indeed. I may have to go the service worker route, or perhaps a web worker if possible.

Nothings exploded so far: https://github.com/DustinBrett/daedalOS/commit/eb958836f1f5e...


Great work Wasmer team :)


Does the exe generation need any runtime like vb needed vbrun.dll back in the day?


No, it's a standalone binary. It compiles the wasm file to native assembly (depending on target), then uses zig build-exe to link libc and libunwind into a final exe file.

$ wasmer create-exe --target x86_64-windows-gnu qjs.wasm -o ./js.exe && llvm-objdump -p ./js.exe | grep DLL

    DLL Name: KERNEL32.dll
    DLL Name: msvcrt.dll
    DLL Name: WS2_32.dll
    DLL Name: ADVAPI32.dll
    DLL Name: USERENV.dll
    DLL Name: bcrypt.dll


Cool! Does this support compiling of games to WASM, with deployment at the edge?


Other than some fantasy consoles like WASM-4, which have some retro-inspired limitations, there isn't really a standard way to do any kind of GUI in Wasm yet. Wasmer has a non-standard way[1], which they hide behind compilation flags, and involves writing to a bitmap framebuffer, so no hardware acceleration.

[1]: https://medium.com/wasmer/wasmer-io-devices-announcement-6f2...


It does, using the wasm4 console target: https://itch.io/jam/wasm4-v2


> support for multi-value functions

Link to example for this? Tried Wasmer about a year ago and had too much trouble passing multiple non-int args with a Rust host (so no JS bindgen)


This test might be useful (although it might be a bit hard to read because of the usage of macros) [1]. We will create a simple example of multivalue to showcase how it can be used

[1]: https://github.com/wasmerio/wasmer/blob/master/tests/compile...




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: