A world to win: WebAssembly for the rest of us
wingolog.org
wingolog.org
It's because you cannot have native performance on something that is still the virtual machine.
Another reservation I have is global migrate-to-the-cloud trend, where I can see heavy-CPU programs like adobe photoshop moving to in-browser, while I feel much more comfortable using natively compiled applications. It's just faster and gives working smoothness feeling. Also when I have a locally installed photoshop or lightroom, nobody requires any money from me. I can have a dedicated laptop for my photos processing, and nobody will take it from me, because I didn't pay for the next month. However this is another story of making people dependant on subcriptions in all cases of our lives...
I don't think this is a Wasm issue. IIRC Google Meet uses WebRTC for encoding, which is the compute-heavy part of a video call. They might use Wasm for background blurring or something like that.
In general I suspect that the issue here is that Skype as a native app can access some video-specific hardware acceleration that the browser can't. CPU-bound workloads should be close to native speed (OP says within 10% of native which tracks with my experience)
> In my case meet drains almost 2x amount of power and after an hour-lasting meeting I have no battery left, but on one-hour meeting on skype I still have 56% of battery.
is comparing apples to oranges via an uncontrolled comparison.
> WebRTC for encoding, which is the compute-heavy part of a video call
On Windows in Chrome, Google Meet will correctly use the same hardware acceleration for video encoding that Skype does. Both will ultimately use DXVA on modern hardware. On macOS, the story is complicated and I know less about Skype's internals.
it is because the laymen simply doesn't know how to account for their own bias. They conceived an experiment to try to show an objective truth, but was in fact biased - and probably didn't even really know it.
This is why science isn't done this way; you need to put in a lot of effort to design the experiment, so that preconceived biases don't show up. Things like double blind, and randomization, etc.
Agreed! Between WebCodecs and WebGPU compute shaders, I think we’re getting closer to this ideal.
Edit: Meet also apparently uses MediaPipe, which in browser does results in heavy WASM/GPU usage which on a native API could go to a NN accelerator instead. It is fair to say that stuff can melt batteries too.
But you can have native performance on a virtual machine by translating your VM code to machine code and just running the machine code. There are ways to sandbox without interpretation. WASM goes to some extent in that direction, but not all the way, mostly for safety.
So it wastes some power. The question is: so what? WASM is attractive because it's an instant deployment. You open a URL, boom. Nothing to explicitly download, install and launch. Nothing to maintain. And eventually uninstall. It removes the friction for apps you use once in a while, or... just once, even.
In engineering & design, efficiency comes in many kinds. You waste power on the user's machine, but you got your foot in the doorstep by them opening your URL and running your app. It's not how many of us, including me, want the world to be, but it... be how it be.
P.S.: The real flip-side is when sites start figuring out ways en masse to profit from your compute by visiting their sites. Crypto mining as one example. Oh well.
Maybe I'm too old fashioned, I don't know. What I know is that creating multiplatform native application is really hell (I did that), and Javascript is much cheaper, that's why everyone is doing electron, which literally launches up another separate google chrome in your memory... Yes, it's cheaper, but memory is much more expensive nowadays, than it used to be when I started programming...
That's usually done by the browser when using WebRTC (except for postprocessing, e.g. background blur), not the application (using WASM or JavaScript).
Some browsers do this in hardware, others don't – just like some native videoconferencing applications are horrible CPU hogs, and others are quite efficient.
JIT compilers are a thing, so this statement is just plain false.
Also, apples to oranges comparison. I’m not saying that in this particular case it is not true, but that can’t be deduced from this datapoint.
Do you know of any JITed languages that approach SIMD optimized native code in terms of performance and overhead?
Even the best ones (eg. LuaJIT) fail to come close to even moderately optimized C code, with much higher memory usage. On top of that, JIT optimizations don't always trigger and you fall back to interpreted levels, which are orders of magnitude more expensive.
And autovectorization is definitely done by HotSpot (I would guess also by V8, though not sure), but autovectorization in itself is very finicky both AOT and JIT, so there is now a stronger move towards user-exposed controls, e.g. Java’s new Vector API, but C# also had something like that for years. Funnily enough, C doesn’t have any standard way to control vectorization, only compiler-specific extensions.
Also, memory layout is a completely different problem space, don’t judge JIT compilers on that. On numerical code they are very competitive with AOT compiled, low-level languages, both JavaScript and Java. Of course if a given object could not be escape analyzed than the semantics doesn’t allow further inlining and somewhere that pointer indirection have to be paid, but don’t forget that besides benchmarks, most real life code in C/C++/Rust whatever will also happily chase pointers, so the difference is again, not as stark as some benchmark may tell you. Also, this is more related to GC+JITted languages, but are not necessary for JIT alone. With that said, I just realized that there is Julia in this exact niche, that also demonstrates my point very well.
> On top of that, JIT optimizations don't always trigger and you fall back to interpreted levels, which are orders of magnitude more expensive.
An optimization “triggering” is exactly similar to what an AOT compiler would do, only with a smaller time/resource budget. What you are getting at - speculative optimizations - are a different story, and are not a necessity in case of a JIT. And they get deoptimized when the assumptions they made for the optimization are proven incorrect (e.g. in java’s case virtual calls may have been replaced by static ones as only a single class implementing the given interface were loaded at the time - but upon loading a new implementation this will have to be deoptimized). You are right that deoptimizations can be expensive, when they go wrong, or in the worst case go into some cycles, but in practice with V8/HotSpot, these work well enough. The initial warmup is more likely to cause some jitter if any.
> Why would LuaJIT be the best?
It was one example out the group of best ones, sorry for not being clear enough.
> Also, memory layout is a completely different problem space, don’t judge JIT compilers on that.
Exactly; you're stuck with the memory floor the language provides you with, JIT or not. This means a fixed minimum cost (resources, heat, electricity etc) that would otherwise not be there.
> On numerical code they are very competitive with AOT compiled, low-level languages
How competitive? I've never seen a benchmark show a JITed language compare to the equivalent program in C, with the few exceptions where the C implementation was written in such a way as to enable the author to say "we're faster than C".
> most real life code in C/C++/Rust whatever will also happily chase pointers, so the difference is again, not as stark as some benchmark may tell you
Oh most definitively. On the other side of that same coin, most real life code in JS/Java/C#/PHP/Ruby consume orders of magnitude more resource than their lower level counter parts.
Often, a lot of that is due to writing idiomatic code in languages where idioms are expensive (eg. `[... new Set(arr)]` in JS), which often also means that underlying libraries and frameworks also use these idioms. Even worse when libraries like lodash/ramda become popular and you have another order of magnitude more overhead compared to the equivalent for loops.
You could of course optimize that, just like you could optimize your C/C++/Rust/Zig program.
> You are right that deoptimizations can be expensive, when they go wrong, or in the worst case go into some cycles
If what you're saying is true than that's great news! My own experiences (>decade ago) of observing other teams experiment with JITed languages showed more pessimistic worst case outcomes (embedded engineers trying out embedded scripting languages).
> Oh most definitively. On the other side of that same coin, most real life code in JS/Java/C#/PHP/Ruby consume orders of magnitude more resource than their lower level counter parts.
Java is actually within the compiled language’s groups’ results with regards to energy efficiency. A good GC can allow to be very power efficient and tradeoff memory for running the CPU — only has to run the GC when it really is close to filling up. After running, it can free the former region in one `nop` by declaring the former region as unused (at least in the moving GC kind).
I personally have pretty bad battery drain from Zoom. I think there's definitely a lot of futures where WebCodecs (for even better hardware accelerated encoding) & WebTransport & Media-over-QUIC open up technical paths to dominate & crush most native app implementations.
And unlike native apps, which rely on mountains of proprietary systems, the web can be a platform where anyone can put together new ideas quickly & easily, that leverage enormously advanced common platforms.
I am just so tired of all the web whining. None of these people have the faintest clue what the web is moving towards, have the slimmest interest in understanding why their gripes are actively being made irrelevant. It's brutal, enduring such strong & wrong anti-vision, having to forever be handling these very loud persistent minorities whose motto is, to quote the band Kula Shaker, "whatever it is I'm against it".
Of course one could go farther by using cpu- and compiler-specific optimizations (for instance SIMD intrinsics), but some of those are also portable to WASM. In general, memory layout optimizations translate directly to the WASM linear heap, and that's by far the most important performance factor before it makes sense to look into platform-specific optimizations.
If macOS decides to run your code on an efficiency core or a mobile device throttles the clock to avoid overheating, you'll lose a lot more performance than just 25%.
Or if some users have a lower end device, or you use different compilers for different target platforms, or a new hardware exploit hits and the mitigation results in a general performance loss.
The only situation where such 'wiggle room' isn't required is when you completely control the environment your code runs in, but in this case you don't need runtime portability nor safety, and thus WASM wouldn't make sense in the first place.
Really excited about Scheme compiling to WebAssembly. A whole world of possibilities indeed!
https://spritely.institute/news/scheme-to-wasm-lambdas-recur...
People need to look at JS, WASM, WebGL/WebGPU and the other browser APIs as a single platform, and use the right parts for the right job, instead of reimplementing JS functionality in WASM and vice versa etc.
Also.
WASM is not "just another ISA" at all, as I explained in other comments throughout. For one it has an opaque call stack and no free jumps inside from one code location to another, unlike any other ISA in the world. This means it's terrible for languages which lean heavily into tail calls and coroutines, among other. It's also bad for GC languages as a custom collector can't compete with JS's GC.
There is already a WASM back-end for Golang, which implements coroutines without tail calls or sparse stacks.
BTW. ISAs with opaque call stacks and verified branch targets, respectively do exist, but I dunno if there is hardware that does both. You could use Intel CET for the latter, and enable "Safe Stack" or a flavour of "Control Flow Integrity" instrumentation in LLVM to emulate the former. There are also projects that recompile existing binaries. Google Fuchsia has Safe Stack enabled for all binaries, except for Golang unfortunately.
As for "just another ISA", there have been CPUs which had separate call- and data-stacks, with the call-stack living on the CPU and not directly accessible to code. In that sense WASM isn't much different then those esoteric CPUs, yet those also implemented "just another ISA".
And even though WASM might not allow free control flow, I yet have to see a noticeable performance difference between WASM and native for this type of "worst case code":
https://github.com/floooh/chips/blob/f5b6684ff6e899429544b21...
I'm not super familiar with WASM, but (according to this article/talk) implementing GC in pure WASM doesn't really work cross-module: in particular, there's no way to trace liveness across modules (e.g. if some JS is holding a reference to one of our WASM values), and the least-privilege/capability approach is lost since we have to grant access to all of our memory at once (e.g. if we're storing the heap as one big buffer).
> just more or less awkwardly
There are hacks and work-arounds, but it's a pretty silly situation when there's already a GC right there for the JS engine. It's important to get the details right when standardising (e.g. to allow future advances, rather than locking-in current techniques), but the current situation of downloading multiple standalone GCs isn't really acceptable.
It's in phase 3 (Implementation Phase): https://github.com/WebAssembly/proposals
No, despite it's "asm", it has no jumps ("goto") to addresses and labels except structured (nested blocks) ones, like in JS, and with a hidden/implicit call stack. Like in JS.
This means if you want tail calls you need to emulate them with similar techniques you'd also use in JS.
So, what else makes JS a less appealing compiler target? Let's unravel this myth.
Is this still true? I don't know if I'm reading this right, but this page says the tail call extension is shipping since Chrome 112:
https://chromestatus.com/feature/5423405012615168
PS: yep, shipped in Chrome 112, but not yet in any other stable browsers version (only in nightly or behind feature flags): https://webassembly.org/roadmap/
But that's an important advancement.
- WebAssembly was designed with delivery-over-HTTP and browser-based in mind. For that reason, it supports streaming compilation - i.e. you can start compiling the code while downloading.
- WebAssembly was designed to have rapid compilation times (resulting in web pages that load quickly), this is supported by having very simple validation rules compared to Java / JVM languages.
- WebAssembly was designed with the concept of a 'host' environment, i.e. the browser.
- WebAssembly was designed to be secure and simple, minimising the overall attack surface.
- WebAssembly was designed to support a great many languages (C, C++, Rust, ...), whereas the JVM was initially design for a single language, Java.
https://stackoverflow.com/questions/58131892/why-the-jvm-can...
Heh?
> embeds a number of historical mistakes
Well, you need history for that first. Wasm won’t be any different.
> makes sandboxing basically impossible
Why would it? It just turned out that whitelisting should be the default approach to security over blacklisting. There is nothing inherent in the JVM that would preclude one from doing that.
WASM is far, far easier to reason about from a security perspective because its orders of magnitude simpler. There is no standard library. All wasm code (including any library code you compile in to your software) runs in an entirely encapsulated virtual machine with no ability to interact with anything outside of its little bubble. (Except for any functions the application explicitly passes in to the wasm module.) The wasm module boundary is fixed and simple, and as a result its much easier to secure.
I'm sure someone will eventually find a sandbox escape for wasm code somehow. But I bet there'll be at least an order of magnitude fewer sandbox escapes in wasm than we've had with java because of the differences in the security model.
[1] https://www.cvedetails.com/vulnerability-list/vendor_id-93/p...
Also, why would we expose the full filesystem api to a theoretical JVM for the Web? The core of the JVM is a simple stack-machine and a GC, there is nothing demanding all these additional hooks to useful, but potentially unsafe APIs. Of course WASM is safe without any outside functionality, so is brainfuck in and of itself.
So you're suggesting we put a subset of the JVM in the browser, with no access to the java standard library?
Why?
You couldn't run any existing java code or any code in other languages without a compiler. It would just be a weird sub-language that nobody really wants to use, with no existing code or libraries. The pressure would be on to add all the crap from the JRE - putting a tension between security (who knows how secure any of that code is) and usability (who wants a language with no standard library?). This has all played out before and java ended up giving up and deprecating SecurityManager.
Even if you succeed, to what end? So we can run java in the browser? So we have 2 average languages instead of 1? Should we add a C# subset next? The beauty of wasm is that any language can target it.
Or would we compile our C, Go, C# and Rust to this new java subset? But that wouldn't work well - java is missing many features which would be needed to run C code properly. You could make it work using some horrible hacks on top of ByteBuffers, but then it'd run much slower than native code. Much slower than wasm runs today. Whats the point when we could just do the same thing on top of javascript? (And we did - it was called asmjs).
I suggest putting a subset of the JVM that has access to many parts of the standard library, but certain APIs would need proper browser permissions, the same way it works with JS today.
It could run the vast majority of the very high quality of Java ecosystem, and every JVM guest language code out of the box. It is also not a bad compile target -- I would argue that most mainstream languages would actually prefer a managed runtime, and C/C++/Rust are the niche. Aren't there orders of magnitude Java+Python+C#+Haskell+... devs that would prefer to write in their language over JS? Sure, you might say that the reason for WASM's existence is mostly the performance gains for small algorithms, and there certainly is a new niche made available thanks to it, but one way or another people will use it simply due to preferring their stack to JS. The performance aspect is also improved to the JS-only world by possibly allowing proper shared-memory multithreading.
> java is missing many features which would be needed to run C code properly
Why would ByteBuffers be a horrible hack? Is it worse of a hack then what C compilers have to do when targeting WASM, like only having structured control flow? It's just an array read mapped to a single instruction, but in context can also be optimized efficiently (e.g. autovectorizing them when they occur in a loop).
GraalVM actually has support for any LLVM language (though their way of interpretation is different enough from the standard JVM bytecode mode that I only mention it as an interesting data point) with quite great performance, certainly comparable to WASM.
Nonetheless, please don't take my possibly argumentative tone as a negative, I enjoy this discussion and you make great points. I also don't dislike WASM, it is imo a net positive thing. I just believe that a JVM-fueled web failed mostly due to politics, not something inherently technical.
Mmm maybe it is fine in java. I've spent a lot of time benchmarking javascript which has a similar set of primitives (typed arrays). I'm not sure how they perform now, but at the time they were always significantly slower than native javascript arrays for some reason.
> GraalVM actually has support for any LLVM language
Cool - I didn't know that! Thats definitely a point in the direction of the jvm being viable.
> Nonetheless, please don't take my possibly argumentative tone as a negative, I enjoy this discussion and you make great points.
I'm enjoying this too. For what its worth, at a big picture level I think it would definitely be technically possible to do what you're proposing. Its just a question of tradeoffs. Is it easier to tame a subset of java that could usefully fit in the browser, or just start fresh? The downside of starting fresh is that we'd need new compilers and optimizers. And the downside of using java is that the security story is much more complicated, and you'd need to figure out how much of the standard library to bring across and figure out how to secure the FFI.
Obviously the wasm team chose the latter. But perhaps if there were more java fans amongst browser vendors, or the choice was made decades ago, I could easily see the JVM being chosen instead of inventing wasm.
Class loaders, reflection, all methods being virtual, and iteration going through an interface make it much harder to get good performance with the complexity and warm-up time of a JIT.
Type erasure and single polymorphic dispatch makes the JVM's object representation a weird fit some languages.
UTF-16 strings are just awful.
Oracle's business practices rightly scare people away from wanting to build on top of anything they control.
The JVM is a very impressive technology, but it's also almost thirty years old and we've learned a lot since then.
Getting C/C++ code running in the browser was the motivation for Emscripten, and eventually this evolutionary branch gave us WASM (via asm.js).
(and at the time there was plenty of competition: Adobe's Alchemy/Flascc which targeted Flash, and Google's (P)NaCl which compiled to native instructions and later (a subset of) LLVM bitcode, but notably, there was no similar attempt (that I know of) of a C/C++ compiler which targeted the JVM)
There is hardly a more open platform than the JVM, its reference implementation is open source, it has an open specification for both the language and the VM with plenty completely independent implementations, and is so big, running business critical infrastructure in basically almost every FAANG, that any single one would alone pay for its continuous development. Also, Oracle has been a surprisingly good steward of the platform, managing to retain almost the whole Java team from the Sun days (remarkably hard to do that at takeovers), increased the pace of its development and finished open-sourcing everything (formerly OracleJDK had proprietary extensions not found in OpenJDK, nowadays only some trademarked logos remain as the sole difference).
So they mostly own only the name’s trademark, which is no big deal. Remember, google vs oracle happened over Sun’s license that explicitly forbade using their software on mobile devices. No such restrictions exist anymore in case of OpenJDK, which has the same license as the Linux kernel.
They are infamous for reimplementing things worse that were well available decades ago.
And?
No one said that the performance concerns reduce to hardware — but at the Java Applets days it was most definitely the primary reason for their slowness. Since then, with the improvements of JITs, it became very fast.
> than a high-level object-oriented garbage-collected system can muster
That’s not a well-defined performance level and the ceiling changes each year.
And V8 has no real parallelism, so for many kind of workloads they are not drop-in replacements.
What happened is that people realized that blacklisting does not work. Whitelisting is the correct approach. There is absolutely zero reason why WASM would be better for that over the JVM — the JVM spec in itself has no visible side effect, not even printing, so it can’t do anything nefarious (besides cpu vulnerabilities, but that also apply to WASM).
And you would run C code in a completely trivial way: you have a huge array which is your memory, and you read/write bytes to it.
> And you would run C code in a completely trivial way: you have a huge array which is your memory, and you read/write bytes to it. That sounds like it would have terrible performance. Would every read of an int have to manually build it from the 4 bytes it's made of? This just seems like something the JVM won't handle that well.
Besides, this would mean that if you want to run a language like C#, which has references and value types (and you can make a reference to a value type from a pointer into a buffer), you would have to emulate them, which will hamper performance, or just use the same strategy as you used for C.
No, a method can have a native implementation, or a compiler intrinsic. Java has ByteBuffers (https://download.java.net/java/early_access/panama/docs/api/... ), and they have put/get{Long,Short,etc}, that will map to either a native single pointer read with the given size, or even optimize to a more efficient read inside the context of a bigger method, say vectorize them inside a loop (as the compiler knows about this method and can handle it specifically).
> Besides, this would mean that if you want to run a language like C#, which has references and value types (and you can make a reference to a value type from a pointer into a buffer), you would have to emulate them, which will hamper performance, or just use the same strategy as you used for C
So we are back at where WASM is? Though I think that there is nothing inherently impossible about mapping C# to more efficient Java primitives, especially that value types are the more constrained semantics, each instance being different is semantically the same, just less optimal. A pointer to a region of the aforementioned ByteBuffer with a special memoryToCSharpObject() that has some compiler intrinsics wouldn't perform too bad, I believe.
Exactly. By the time you've done all that, whats the point? You'll have reimplemented wasm on top of the jvm in a way that:
- Can't use any of the java standard library (which all existing java code depends on)
- So you also can't use any existing java code
- You need a compilation step for any existing code in other languages to convert it into your special limited java syntax
- And the result will run slower than wasm because of the extra layer of abstraction going on
The one advantage is that you can output everything as standard .class files, so it'll be easier to pull this code into an existing java application.
And yes, you could absolutely do that if you want and you see value in it. Heck - maybe it'd be nice to have a wasm-to-java-class converter to let you reuse all the wasm infrastructure.
But this all sounds like the java equivalent to asmjs, which we already tried. Asmjs was the precursor to wasm. It was built on top of javascript primitives in much the same way as the proposal here builds on top of java primitives. As I understand it, the reason we ended up with wasm instead of asmjs was that:
- Wasm was easier to optimize, had a smaller file size and was faster to load at runtime (since you don't need a javascript compiler)
- Its much easier to make VMs for wasm in lots of languages and environments. Wasm modules can be loaded into programs written in python, rust, C, java, go, javascript, etc without some weird unnecessary dependency on javascript.
One can surely cherry-pick quite a lot out of it that are safe to use, e.g. anything not using `native` implementation can as per the former definition of JVM interpreter, also end up being safe. So many existing code would run without any change.
> Re: compilation step
Why? It has nothing to do with Java, the language, only the JVM class file format. Scala/Kotlin produce bytecode directly, not Java code.
> Run slower
Why would it? Wasm can run fast having grown out from asm.js, yet a JITted runtime that runs half of the internet can't?
> Its much easier to make VMs for wasm in lots of languages and environments
There are plenty toy JVMs out there as well, the core really is not difficult.
And the point of all this would be that large chunks of the JVM could have been reused, that runs on every platform with top notch performance already, without all the growing pains that WASM will experience. Also, the JVM's type safe cross-language capabilities are already here, while they are very experimental and rudimentary in case of WASM. I can just call a Kotlin class from Clojure, or JPython or whatever, and vice versa.
Java already tried - many times - to have a "safe subset" of the language. As I understand it, the effort was finally abandoned with the deprecation of SecurityManager. But even if you made a safe subset of java, you've only gone from 1 working browser language (javascript) to 2 (javascript and java). Well, and the compile-to-JS & compile-to-JVM languages.
> Also, the JVM's type safe cross-language capabilities are already here
But that leaves out a lot of languages that people care about. Important languages, like C, C++ and Rust, C#, Go and Python. These languages don't compile to the JVM because of limitations in the java bytecode format and type system.
I mean, how would you make C or Go run on the JVM?
Perhaps java's type system could be extended to support these languages too. But it would probably take 20 years of committee meetings to do it. And the time to start that work was 20 years ago. At this point its much easier to start fresh with something new like wasm.
[Edit: In another thread you mentioned graalvm has been made to support any LLVM code. Thats great, and perhaps addresses this point entirely. I don't know enough about it to know.]
> Why would it [run slower]? Wasm can run fast having grown out from asm.js, yet a JITted runtime that runs half of the internet can't?
The challenge is making existing C code run at near-native speeds. How would you do that with your proposal? You'd need to first compile your C to java classes and then ran the code in the JVM. But java has no native pointers or direct access to an allocator. Java's GC alone would incur a massive performance penalty to C code.
Asmjs was made fast by making javascript engines contain a second, separate compiler for the asmjs dialect. The compiler detected asmjs explicitly and essentially used asmjs as a weird, expensive syntax for a different language. I guess java could do that too. We could have a special .class file syntax subset and add special compiler logic to the jvm to optimize that particular dialect. But if you're going to go down that road, why bother with the JVM? Javascript is already in the browser. For that matter, why not just compile your java classes to javascript?
> There are plenty toy JVMs out there as well, the core really is not difficult.
I'm confused - are you proposing just porting across the core of java, or java with a lot of its standard library? Given the size of the JRE, those are two very different propositions! The former is possible but pretty useless, and the latter is a massive job that the java community has already tried and as I understand it, eventually given up on.
> Also, the JVM's type safe cross-language capabilities are already here,
Oh no, this keeps getting worse. You want to put java's FFI system in browsers too?
The problem with Java's various FFIs is that (AFAIK) they're not designed to be a security boundary. We'd need to redesign them all. The surface area is massive and given java's historically abysmal security record, I don't trust the java engineers to make any of this stuff safe or secure. And neither should you.
No, it sounds like you want to bring most of the JVM into the browser to solve a problem I don't have (run existing java code in the browser). And this still doesn't address the problem that wasm solves (let us run any language in the browser, safely and without a loss in performance). And I can't see any straightforward way to address the security problems or the performance problems that this would entail.
In comparison, I'm much happier with the design of wasm. By making a small, simple new bytecode format which explicitly supports C and C-like languages, all wasm languages run fast by default. Wasm is dead easy to sandbox and easy to audit. And this gives us the best of both worlds, since we should be able to compile Java to wasm like any other language. Better yet - this way you can bring in as much of the JVM as you want into your projects, and there's no need to do the solve the impossible problem of making the JVM secure.
Firefox and Chrome actually have support for the new GC and threading support in wasm. That's behind a few feature flags. But e.g. Kotlin's new wasm compiler depends on that and manages to ship binaries that are quite small. That compiler is also being used for a new experimental target for compose multiplatform, which is based on Google's Android Jetpack Compose and extends it to other platforms (IOS, Desktop, and Web). Web now comes in two variants: html & kotlin/js and canvas + wasm. The latter renders using the same graphics libraries used on Android and IOS but compiled to wasm. None of this stuff is ready yet because the tooling and frameworks are pre-alpha quality and it requires feature flags to be set by the user. But, this is starting to look like a nice alternative stack to things like flutter and react native for cross mobile, desktop, and web development.
The feature flags are likely coming off fairly soon. Safari is a bit behind. 2024 is going to be interesting. I'm guessing there will be a whole lot of activity around this in most commonly used languages and stacks.
The other problem is that the "bring your own GC" model means if you use WASM in the browser, you end up having 2 garbage collectors for your program. And that makes sharing objects between javascript and the wasm bundle much more difficult & uglier. You essentially need to do manual memory management for any object thats shared across the wasm boundary to make sure its freed at the right time.
Having a unified GC means object references can be passed naturally from javascript to C# and back without any special code at the boundary.
That's annoying. I was hoping WASM would be a way to break out of the js/java/swift/ObjC stranglehold, not another baton to enforce such tyranny. It would be cool if they were targeting toolkits like QT instead.
(also not sure how Qt fits in here, but it also has WASM support: https://www.qt.io/qt-examples-for-webassembly, but IMHO Qt is way too bloated for this sort of thing)
In the end, WASM running in browsers can only use browser features that are also available to Javascript, e.g. for rendering that would be canvas-2d, WebGL, WebGPU or the DOM). But at least WebGL and WebGPU are close enough to similar native 3D APIs that you can share some code between native ports and WASM running in browsers - but it still makes sense to use a higher level graphics libraries which abstracts over the 3D-API differences, or alternatively use wgpu.rs or libdawn in the native versions (which are the standalone native WebGPU libraries used by Firefox and Chrome).
The article first talks about difficulties a ship-your-own-GC faces, and enumerates workarounds for them (slide "GC and WebAssembly 1.0 (3)" and coupe of next ones).
Then it starts talking about the planned GC support extension in WebAssembly and decides to go with that.
Besides Blazor, the WebAssembly Go port[1] does this as well.
Garbage collection can now be delegated to the WASM runtime instead (e.g. see the short description here: https://chromestatus.com/feature/6062715726462976)
There's this and other similar projects: https://github.com/helins/wasm.cljc
Here's is my ultra simple example page which I will eventually update with the progress from the private app I am doing.
https://github.com/iainctduncan/s7-wasm
Edit to clarify: I am using s7 specifically because that's the one I use in Scheme for Max, my main OSS project. It is great for computer music.
However, I hope I'll be proved wrong and the new gc facilities will be a great success.
Like, does application code rely of GC implementation details to be performant that might be different in JS' implementation?
- stack support of the hs-wasm-cabal
- lots of rewriting to remove C string, etc, from many packages:
Also, nothing is stopping a web page author from implementing a simple webassembly interpreter in javascript and using that to execute the code if the browser's webassembly engine has been turned off.
Is WebAssembly now able to run it outside a web browser or this guy is just "inflating" results, to put it mildly and not call him a liar. Because last I checked, there is no world where a browser application is in similar performance with a native one.
Being flamed on Reddit by desperate Java developers wishing for WASM who emotionally cannot figure out JavaScript to save their careers was the straw that broken the camel's back. I deleted my Reddit account and never looked back. Dire indications of far deeper problems not specifically related to Java, JavaScript, or WASM.
In a world without WebAssembly, this would mean that all application software will be written in JavaScript. This is a bad outcome! JavaScript is a fine DSL for GUIs, but it is not a great programming language for applications, especially when you get into graphically-intensive, data-intensive, scientific, etc. software.
Wasm is an out that allows developers to write the application core in another language like Rust or C++, as they would on the desktop, while still delivering software in the browser.
A bunch of products are quietly doing this already. (One is in the process of a $20bn acquisition.)
Are they? It’s not like C++ is tossing around pixels itself, it commands the GPU to do so. Sure, there is a point where the speed at which the CPU side of data being supplied will be the bottleneck, but it is so far above typical desktop applications that it is incorrect to call managed languages unfit for graphically intensive applications (as shown by all those indie games).
Also, there are many different kinds of GCs, and you can limit the max pause time to very low values for a slightly lower throughput (note: this same tradeoff will happen without a GC also, these two are very often opposite ends of the same spectrum) to the point that unless you are using special real-time kernel with all the necessary process configs, your OS’s scheduler will introduce bigger pauses.
Of course in reality almost no one bothers because "the user can buy a newer machine anyway"-sort of thinking, sadly.
If you got flamed, I imagine it was more about tone than content :)
Sure, not all languages, but getting Rust and C/C++ out-of-the-box for a start seems to be worth it.
Also, it's an open source runtime, so if you integrated it, you get improvements from the community, which is a huge gain for small projects.
There is amazing advantage though to just exposing C++/Rust applications without requiring a separate installation or executable for both security and convenience, but I am not seeing much of this in the wild. I think the sand boxed nature of WASM is a bridge too far for many C++/RUST application developers who would then need to include a tremendous number of support library they take for granted outside the browser.