> asm.js was Mozilla’s response to the question posed by NaCl and PNaCl: how can the web run code at native speeds?
Had it been today, Chrome would have just pushed NaCl and PNaCl no matter what, and then everyone would complain why Safari and Firefox aren't keeping up with "Web" standards.
I still maintain the notion we're in the wrong timeline, one where PNaCl died and instead of a worthy, timely successor we end up being boiled alive in a soup of Electron apps.
I really thought, for a time, that we'd be doing everything in the browser. And in a way that's increasingly true, but it all just feels worse than ever. I like WASM and I want to like WASM but the rate of maturity within the ecosystem is incredibly abysmal.
What's worse is that we should all be running our untrustworthy AI tools and their outputs in precisely such a sandbox, and companies are selling the reverse: hosted sandboxes, hosted JS-based VMs.
I guess that was always the problem: there was never any money in a client-side sandbox.
I do understand why NaCL and PNaCL are undesirable and why wasm is much better, but as a student the NaCL ssh app had saved my computer science homeworks more than once, and this is something that still doesn't have an alternative although I rarely would need it nowadays.
There were 3 systems, all with interesting differences.
The original NaCl was a 'validated subset' of native CPU machine code (e.g. actual x86 machine code with some instructions and instruction sequences disallowed which would allow to escape the sandbox).
The next iteration was P(ortable)-NaCl which replaced the native machine code with a subset of LLVM bitcode, which was then compiled at load time. Unfortunately with this step NaCl lost most of its advantages. Startup time was atrocious because it was basically the second half of the LLVM compilation pipeline (from LLVM-IR to machine code). LLVM-IR also isn't actually great as CPU-agnostic bytecode.
WASM was designed from the ground up as CPU agnostic bytecode that's also much easier and faster to validate.
The only major advantage of PNaCl vs early WASM was that PNaCl supported shared-memory threading right from the start (this is still knee-capped in WASM because of the COOP/COEP response header requirement).
...apart from Emscripten => asm.js => WASM, and Google's NaCl/PNaCl there was also a system by Adobe (Flascc/Alchemy(?) I forgot all the names this went through) to compile C and C++ code into Adobe Flash bytecode.
I have an ancient blogpost from 2012 which compares the three (and where I have been flabbergasted by how well Emscripten actually worked - and this was even before asm.js - the linked demo is unfortunately no longer up):
Pepper was a pun on Native Client (since NaCl = salt). Pepper Plugin API (PPAPI) was Google's more secure version of NPAPI (Netscape Plugin API). Flash Player was essentially the only thing using NPAPI/PPAPI by the end of its life.
The most common plugins were Flash, Silverlight, Adobe Reader, and the Java applet plugin, and I think all of those were in mildly common use when plugins were on their last legs.
> The only major advantage of PNaCl vs early WASM was that PNaCl supported shared-memory threading right from the start (this is still knee-capped in WASM because of the COOP/COEP response header requirement).
Presumably that is because PNaCl predated spectre (?)
You mean Chrome would have pushed it, Apple would have filibustered it by refusing to comment (via lack of investment in the WebKit team), and then gullible folks on the internet would defer to them.
(I will note that Apple seems to have upped WebKit investment this decade since their regulatory problems started in earnest - so it's possible this would end differently today)
I mean that's still basically what they tried to do at the time. They were trying to get them through web standards committees and everything.
IIRC a big reason it didn't end up working was because NaCl was such a "big" technology and asm.js such a "small" one that asm.js was able to reach production-ready first despite starting work several years later.
That's sad but sensical. Fun fact, Figma originally started as a fully C++ codebase, and Asm.js was key in proving that it would be possible to run a design tool in the browser. The switch to WebAssembly didn't happen until after there were paying customers, and provided nice improvements to load time (Asm.js is still JS which the bundle size is bigger and requires the code to be parsed into an AST, unlike WASM).
What's so sad about it? It was just a compilation target that made sense at one point in time. Its like being sad about i386-unknown-freebsd1 being dropped.
(And to those who haven't encountered this before, I strongly recommend a watch. It may be the greatest tech talk of all time, for certain values of greatest.)
With this technology's death, the thread of prophecy is severed. Restore a saved game to restore the weave of fate, or persist in the doomed world you have created.
Not really: ASM.js became WASM. What killed the possibility of WASM being The One Way to run everything is AI... the one wildcard that Gard Bernhardt didn't predict.
I re-watch that presentation two or three times a year because it's a great example of how to give a presentation, how to structure your slide deck to complement your presentation, and a surprisingly educational tour of the permission rings architecture of operating systems.
And at some point we're going to have a period or war and our psychological attachments to old programming paradigms will be released so that we can move on to a more advanced way of doing things (but that won't stop your bank from running YavaScript for at least another 85 years).
It was fun to see the rise of asm.js, which was a precursor to Web Assembly. Some of the early demos were so cool to see; Unreal Engine running in the browser. :) Bitter sweet to see the sun set here, but it did lead to much better things.
I’ll never forget watching Gary Bernhardt give his talk on JavaScript.[0] Was my introduction to asm.js, and the rabbithole associated with compiling code to run in the browser.
12 years on, it’s shocking how much of his fiction became reality.
And if not for the rise of AI it's possible that WASM as a machine-level compilation target for all languages might have happened. As much as Gary predicted he didn't see AI coming.
I believe the idea is that you don't care what language is being used if you aren't going to look at it anyway. Given that premise, the AI can write JavaScript instead of something you need to compile separately.
Isn't Asm.js better just for the fact that I can call web apis directly without shims? Or moving data in and out? I'd love to commit totally to webassembly but still seems very limited, am I wrong?
Depends on what do you mean about by web apis. Fetch API for example is not part of asm.js subset of JavaScript. You going to need a javascript shim on both cases. However, like the siblings comment says: overhead comes from conversion between big structures.
Wasm can also call web apis directly. The overhead you hear about is in translating complex types like nested dicts etc between formats. But wasm runs inside the js runtime
(compiling legacy code with legacy versions of Emscripten is quite frustrating, almost as bad as updating your JS code to be compatible with accumulated changes in the Emscripten ABI)
Binaryen used to have an asm2wasm tool, but I believe it has been deprecated. I couldn't find any other equivalent. At least the asm.js code will keep working even with asm.js opts disabled, but it would be nice to have a translator.
> But wasm is too isolated from javascript. From my limited use of it, I was considering trying to compile to asmjs instead
asmjs is going to be strictly more limited in interacting with JS than wasm. You're basically limited to simple number values and array buffers. Whereas wasm now a days has GC types and can hold onto JS value using externref.
> But more important for what i was trying to do, you can't zero copy buffers from js to wasm
This isn't a fair comparison. Wasm was severely limited when it was first implemented and it had the advantage of a decade of improvements. Asm.js has had zero improvements in that same time frame.
Had WASM not been adopted we would have SIMD in JS ( probably via asm.js) by now. Because we didn't, JS just cannot compete with WASM in many computationally heavy workflows. We'd also have general purpose JS to Asm.js compilation, with few API restrictions, making writing it much easier.
Well, I haven't actually tried the asm.js approach for this, so maybe I'm missing something.
But since asm.js is just (a subset of) javascript, I assumed I could just pass ArrayBuffers around.
With wasm, I could pass a Uint8Array out of it. If I wanted to pass it in, I had to call malloc from the javascript side to allocate in the wasm heap. But since I already had an arraybuffer (from a file upload), that meant an extra copy.
Oh my God. That's so exciting. I did a prototype a while back for writing UDFs in WASM for a query engine. The fact that everything needed to be copied in and out of the environment killed it. Excited to try it again if/when this lands
IIRC Emscripten has removed asm.js support around 2020, and that was probably the most important toolchain that ever supported asm.js (maybe followed by Rust, don't know if they still support it though)
> You can't call most web apis from wasm.
You can't from strict asm.js either, since it only supports numbers (no JS strings or objects) and manages the C heap in an ArrayBuffer object just like WASM.
> But more important for what i was trying to do, you can't zero copy buffers from js to wasm.
Same problem as above, you need to call out into "real" Javascript from asm.js and you can't map other ArrayBuffers directly into the 'asm.js heap' either, a copy is needed. The "Javascript FFI" really isn't much different between asm.js and WASM.
Perhaps I'm misunderstanding, but doesn't asm.js have the same restrictions? I.e. you can't call web APIs directly from asm.js code, you still need special handling for "foreign" functions.
Depends how you want to look at it. On one side asm.js is just JavaScript with special JIT handling, so you should be able to mix them. On the other side you have C/C++/Rust/whatever compiled to asm.js which needs to go through hoops to call normal JavaScript code
I don't think that is true though. The spec make it clear that it only has access to a limited subset of the JS standard libraries and specially registered foreign functions:
> An asm.js module can take up to three optional parameters, providing access to external JavaScript code and data:
> - a standard library object, providing access to a limited subset of the JavaScript standard libraries;
> - a foreign function interface (FFI), providing access to custom external JavaScript functions; and
> - a heap buffer, providing a single ArrayBuffer to act as the asm.js heap.
AFAIK as soon as you'd start mixing idiomatic JS and asm.js, you lose the "special sauce", you only got the special asm.js treatment in browsers when putting a "use asm" at the top of a source file, and that would prevent using regular JS features in the same file.
Just try the asm.js subset and see how it performs for you, I remember that even without the special asm.js support in browsers Emscripten output performance was surprisingly good
It will still work. asm.js is just regular JavaScript code, after all. It just won't parse/run as fast as custom pipeline for asm.js. My guess is that you will not notice much difference unless you have a really huge application.
It would have been nice if they had mentioned Luke Wagner, who's idea it all was and who created the first implementation, as well as one of the main driving forces behind wasm.
Asm.js was never needed as a legacy mechanism, as it was just a compilation target for native code. There was nothing that it needed to remain backwards compatible with, all asm.js code was new code.
OTOH asm.js can be retired now thanks to being backwards compatible with plain JS.
It allowed it to be an experiment that could have been quickly rolled out without a risk of forever lingering as a back-compat requirement for browsers.
In SpiderMonkey, asm.js code has been compiled by exactly the same pipeline as wasm since at least 2019. In fact, the way we compile it is literally to construct a pseudo-wasm module and run it through our wasm compiler (with a few flags to tweak the behavior to fit the asm.js semantics). In other words, if you're running asm.js in Firefox, you're literally just running wasm anyway, so how could it possibly be faster?
Furthermore, if you use wasm, you'll have fewer bounds checks (because of better memory allocation strategies[1]), access to SIMD, bulk memory operations, and a host of other niceties that have been added to wasm over the years. If your asm.js code is outperforming someone else's wasm code, that probably just means their wasm code is worse.
asmjs is about the same speed in chrome and firefox (with asm optimizations still enabled) but wasm is slow as hell in chrome, asm still better.
side note: someone mentioned native crypto.subtle, but that doesn't have incremental hashing so can't use it for large files. however I do use it in practice for smaller files.
Requires a secure origin. If you serve a local (but non-localhost) SPA over HTTP then you're blocked from using crypto.subtle.digest. At least, that is one reason I have seen a hand-rolled SHA-256 deployed.
Congratulations, two spectacularly wrong 'facts' in one short sentence is quite an achievement ;)
It's true that in the beginning (around 2017), WASM wasn't much faster than asm.js, but meanwhile WASM has seen real performance improvements.
Featurewise, asm.js is much closer to WASM than to regular JS, it definitely cannot do everything that regular JS can do (mainly because asm.js is limited to the Number type, it cannot deal with JS strings or objects).
Faster? I'm not sure about that. Maybe if you are doing a lot of talk between the compiled and JS runtime/DOM. But otherwise WASM has been much further developed in both Firefox and Chrome.
I don't think Chrome ever did an asm.js specific optimization.
Yes, but GC is still useless for languages with interior pointers, some features require gimmicks with server configuration, and for most languages we aren't any way closer to -march=wasm and that's all.
We still need to download half Internet for emscripten, plus whatever tools are being used on top. Although it is somewhat simpler for those that build on top of binaren.
> asm.js was Mozilla’s response to the question posed by NaCl and PNaCl: how can the web run code at native speeds?
Had it been today, Chrome would have just pushed NaCl and PNaCl no matter what, and then everyone would complain why Safari and Firefox aren't keeping up with "Web" standards.
I still maintain the notion we're in the wrong timeline, one where PNaCl died and instead of a worthy, timely successor we end up being boiled alive in a soup of Electron apps.
I really thought, for a time, that we'd be doing everything in the browser. And in a way that's increasingly true, but it all just feels worse than ever. I like WASM and I want to like WASM but the rate of maturity within the ecosystem is incredibly abysmal.
What's worse is that we should all be running our untrustworthy AI tools and their outputs in precisely such a sandbox, and companies are selling the reverse: hosted sandboxes, hosted JS-based VMs.
I guess that was always the problem: there was never any money in a client-side sandbox.
I do understand why NaCL and PNaCL are undesirable and why wasm is much better, but as a student the NaCL ssh app had saved my computer science homeworks more than once, and this is something that still doesn't have an alternative although I rarely would need it nowadays.
Its like natural selection, maybe not the best traits win overall but one that is the most popular choice because everyone is a webdev.
What are the key differences between PNaCl and WASM?
There were 3 systems, all with interesting differences.
The original NaCl was a 'validated subset' of native CPU machine code (e.g. actual x86 machine code with some instructions and instruction sequences disallowed which would allow to escape the sandbox).
The next iteration was P(ortable)-NaCl which replaced the native machine code with a subset of LLVM bitcode, which was then compiled at load time. Unfortunately with this step NaCl lost most of its advantages. Startup time was atrocious because it was basically the second half of the LLVM compilation pipeline (from LLVM-IR to machine code). LLVM-IR also isn't actually great as CPU-agnostic bytecode.
WASM was designed from the ground up as CPU agnostic bytecode that's also much easier and faster to validate.
The only major advantage of PNaCl vs early WASM was that PNaCl supported shared-memory threading right from the start (this is still knee-capped in WASM because of the COOP/COEP response header requirement).
...apart from Emscripten => asm.js => WASM, and Google's NaCl/PNaCl there was also a system by Adobe (Flascc/Alchemy(?) I forgot all the names this went through) to compile C and C++ code into Adobe Flash bytecode.
I have an ancient blogpost from 2012 which compares the three (and where I have been flabbergasted by how well Emscripten actually worked - and this was even before asm.js - the linked demo is unfortunately no longer up):
https://floooh.github.io/2012/10/23/mea-culpa.html
> (Flascc/Alchemy(?) I forgot all the names this went through)
Crossbridge was its third and most recent name.
Pepper.js is another interesting project from around this time that didn't pan out.
https://github.com/google/pepper.js/
Wasn't pepper the P in PNaCl?
The P in PNaCl is Portable.
Pepper was a pun on Native Client (since NaCl = salt). Pepper Plugin API (PPAPI) was Google's more secure version of NPAPI (Netscape Plugin API). Flash Player was essentially the only thing using NPAPI/PPAPI by the end of its life.
The most common plugins were Flash, Silverlight, Adobe Reader, and the Java applet plugin, and I think all of those were in mildly common use when plugins were on their last legs.
> The only major advantage of PNaCl vs early WASM was that PNaCl supported shared-memory threading right from the start (this is still knee-capped in WASM because of the COOP/COEP response header requirement).
Presumably that is because PNaCl predated spectre (?)
Indeed, NaCl and PNaCl would have been hit by Meltdown/Spectre at least as badly as SharedArrayBuffer.
You mean Chrome would have pushed it, Apple would have filibustered it by refusing to comment (via lack of investment in the WebKit team), and then gullible folks on the internet would defer to them.
(I will note that Apple seems to have upped WebKit investment this decade since their regulatory problems started in earnest - so it's possible this would end differently today)
I mean that's still basically what they tried to do at the time. They were trying to get them through web standards committees and everything.
IIRC a big reason it didn't end up working was because NaCl was such a "big" technology and asm.js such a "small" one that asm.js was able to reach production-ready first despite starting work several years later.
The big difference was that they lacked the market share they enjoy nowadays, with their forks and Electron crap.
That's sad but sensical. Fun fact, Figma originally started as a fully C++ codebase, and Asm.js was key in proving that it would be possible to run a design tool in the browser. The switch to WebAssembly didn't happen until after there were paying customers, and provided nice improvements to load time (Asm.js is still JS which the bundle size is bigger and requires the code to be parsed into an AST, unlike WASM).
What's so sad about it? It was just a compilation target that made sense at one point in time. Its like being sad about i386-unknown-freebsd1 being dropped.
What’s sad about that is we could have had a clean, native, desktop Figma application.
So the death of asm.js is upon us? We are drifting away from the timeline of the prophecy:
https://www.destroyallsoftware.com/talks/the-birth-and-death...
(And to those who haven't encountered this before, I strongly recommend a watch. It may be the greatest tech talk of all time, for certain values of greatest.)
With this technology's death, the thread of prophecy is severed. Restore a saved game to restore the weave of fate, or persist in the doomed world you have created.
Not really: ASM.js became WASM. What killed the possibility of WASM being The One Way to run everything is AI... the one wildcard that Gard Bernhardt didn't predict.
Yagrum Bagarn has something for you.
I re-watch that presentation two or three times a year because it's a great example of how to give a presentation, how to structure your slide deck to complement your presentation, and a surprisingly educational tour of the permission rings architecture of operating systems.
And at some point we're going to have a period or war and our psychological attachments to old programming paradigms will be released so that we can move on to a more advanced way of doing things (but that won't stop your bank from running YavaScript for at least another 85 years).
Don't worry, YavaScript will live forever.
In Germany, it's still not uncommon to hear Yava and YavaScript.
I understand that Jawohl is still quite popular there, but JawohlScript adoption is sadly lagging.
I still refer to it as YavaScript much to the confusion of junior devs. I just tell the new kids: "you had to be there..."
Just substitute asm.js with WASM and you're still on the right track.
If we substituted war with COVID we aren't that far off as both happened in 2020. We still have to wait till 2035 to see if true.
A long time ago, I wrote a small chapter in a WebGL book on asm.js.
https://webglinsights.github.io/
It was fun to see the rise of asm.js, which was a precursor to Web Assembly. Some of the early demos were so cool to see; Unreal Engine running in the browser. :) Bitter sweet to see the sun set here, but it did lead to much better things.
I’ll never forget watching Gary Bernhardt give his talk on JavaScript.[0] Was my introduction to asm.js, and the rabbithole associated with compiling code to run in the browser.
12 years on, it’s shocking how much of his fiction became reality.
[0] https://www.destroyallsoftware.com/talks/the-birth-and-death...
And if not for the rise of AI it's possible that WASM as a machine-level compilation target for all languages might have happened. As much as Gary predicted he didn't see AI coming.
wait how did AI impede wasm?
I believe the idea is that you don't care what language is being used if you aren't going to look at it anyway. Given that premise, the AI can write JavaScript instead of something you need to compile separately.
Asm.js is dead! Long live WebAssembly!
To be fair, I thought asm.js was deprecated a few years ago with emergence of wasm.
Isn't Asm.js better just for the fact that I can call web apis directly without shims? Or moving data in and out? I'd love to commit totally to webassembly but still seems very limited, am I wrong?
Depends on what do you mean about by web apis. Fetch API for example is not part of asm.js subset of JavaScript. You going to need a javascript shim on both cases. However, like the siblings comment says: overhead comes from conversion between big structures.
Wasm can also call web apis directly. The overhead you hear about is in translating complex types like nested dicts etc between formats. But wasm runs inside the js runtime
Hmmm, need a asm.js -> WASM transpiler maybe.
(compiling legacy code with legacy versions of Emscripten is quite frustrating, almost as bad as updating your JS code to be compatible with accumulated changes in the Emscripten ABI)
Binaryen used to have an asm2wasm tool, but I believe it has been deprecated. I couldn't find any other equivalent. At least the asm.js code will keep working even with asm.js opts disabled, but it would be nice to have a translator.
I personally think this is a mistake. But I'm not sure how much it matters. It's not like a lot of people were using asm.js still AFAIK.
But wasm is too isolated from javascript. From my limited use of it, I was considering trying to compile to asmjs instead.
But I wasn't sure that emscripten still fully supported it.
You can't call most web apis from wasm.
But more important for what i was trying to do, you can't zero copy buffers from js to wasm.
Everything is a trade off. The isolation is a good thing, but also a bad thing.
> But wasm is too isolated from javascript. From my limited use of it, I was considering trying to compile to asmjs instead
asmjs is going to be strictly more limited in interacting with JS than wasm. You're basically limited to simple number values and array buffers. Whereas wasm now a days has GC types and can hold onto JS value using externref.
> But more important for what i was trying to do, you can't zero copy buffers from js to wasm
I'm pretty sure you can't do that with asmjs either. There is a proposal for zero-copy buffers with wasm: https://github.com/WebAssembly/memory-control/blob/main/prop...
This isn't a fair comparison. Wasm was severely limited when it was first implemented and it had the advantage of a decade of improvements. Asm.js has had zero improvements in that same time frame.
Had WASM not been adopted we would have SIMD in JS ( probably via asm.js) by now. Because we didn't, JS just cannot compete with WASM in many computationally heavy workflows. We'd also have general purpose JS to Asm.js compilation, with few API restrictions, making writing it much easier.
> Asm.js has had zero improvements in that same time frame.
WASM is that evolution of (strict mode) asm.js. The two really aren't all that different from what they can and can't do.
Well, I haven't actually tried the asm.js approach for this, so maybe I'm missing something.
But since asm.js is just (a subset of) javascript, I assumed I could just pass ArrayBuffers around.
With wasm, I could pass a Uint8Array out of it. If I wanted to pass it in, I had to call malloc from the javascript side to allocate in the wasm heap. But since I already had an arraybuffer (from a file upload), that meant an extra copy.
Oh my God. That's so exciting. I did a prototype a while back for writing UDFs in WASM for a query engine. The fact that everything needed to be copied in and out of the environment killed it. Excited to try it again if/when this lands
IIRC Emscripten has removed asm.js support around 2020, and that was probably the most important toolchain that ever supported asm.js (maybe followed by Rust, don't know if they still support it though)
> You can't call most web apis from wasm.
You can't from strict asm.js either, since it only supports numbers (no JS strings or objects) and manages the C heap in an ArrayBuffer object just like WASM.
> But more important for what i was trying to do, you can't zero copy buffers from js to wasm.
Same problem as above, you need to call out into "real" Javascript from asm.js and you can't map other ArrayBuffers directly into the 'asm.js heap' either, a copy is needed. The "Javascript FFI" really isn't much different between asm.js and WASM.
Perhaps I'm misunderstanding, but doesn't asm.js have the same restrictions? I.e. you can't call web APIs directly from asm.js code, you still need special handling for "foreign" functions.
Depends how you want to look at it. On one side asm.js is just JavaScript with special JIT handling, so you should be able to mix them. On the other side you have C/C++/Rust/whatever compiled to asm.js which needs to go through hoops to call normal JavaScript code
I don't think that is true though. The spec make it clear that it only has access to a limited subset of the JS standard libraries and specially registered foreign functions:
> An asm.js module can take up to three optional parameters, providing access to external JavaScript code and data:
> - a standard library object, providing access to a limited subset of the JavaScript standard libraries;
> - a foreign function interface (FFI), providing access to custom external JavaScript functions; and
> - a heap buffer, providing a single ArrayBuffer to act as the asm.js heap.
From http://asmjs.org/spec/latest/#introduction:~:text=External%2...
You can't mix them. It won't pass validation, and will fail to be optimized as asm.js.
In asm.js you have to treat JS functions and objects as special extern values, just like in WASM.
asm.js - when validated and optimized - is closer to WASM serialized to a JS-like syntax than actual JS.
> so you should be able to mix them
AFAIK as soon as you'd start mixing idiomatic JS and asm.js, you lose the "special sauce", you only got the special asm.js treatment in browsers when putting a "use asm" at the top of a source file, and that would prevent using regular JS features in the same file.
There goes my plan to use js code generation at runtime to make my algorithms faster. Doing this with wasm will be much harder.
Generating wasm code at runtime is pretty easy (I'd imagine easier than generating valid asm.js code). We have a little library for our tests that handles a lot of it: https://searchfox.org/firefox-main/source/js/src/jit-test/li...
There's still AssemblyScript? It might meet your requirements, unless I'm misunderstanding you or the features of it.
https://www.assemblyscript.org/
Just try the asm.js subset and see how it performs for you, I remember that even without the special asm.js support in browsers Emscripten output performance was surprisingly good
In fact, I think it was only firefox that made a special JIT route. Chrome moved optimizations into the regular JIT.
It will still work. asm.js is just regular JavaScript code, after all. It just won't parse/run as fast as custom pipeline for asm.js. My guess is that you will not notice much difference unless you have a really huge application.
There are some WAT compilers that are small and fast for running in the browser.
Never saw those monkey prints before
https://monkeyink.com/ink/blog/archives/2016/08/_this_is_a_f...
"The image is a collage of antique open source art reflecting the open source code."
The SpiderMonkey team always had t-shirts made up of these.
We'll drink again in Valhalla (not the JDK project, the one with much carousing).
It would have been nice if they had mentioned Luke Wagner, who's idea it all was and who created the first implementation, as well as one of the main driving forces behind wasm.
Asm.js was never needed as a legacy mechanism, as it was just a compilation target for native code. There was nothing that it needed to remain backwards compatible with, all asm.js code was new code.
https://acko.net/blog/on-asmjs/
OTOH asm.js can be retired now thanks to being backwards compatible with plain JS.
It allowed it to be an experiment that could have been quickly rolled out without a risk of forever lingering as a back-compat requirement for browsers.
Sad day. I have a sha256 hasher in asm.js that's faster than any wasm solution.
In SpiderMonkey, asm.js code has been compiled by exactly the same pipeline as wasm since at least 2019. In fact, the way we compile it is literally to construct a pseudo-wasm module and run it through our wasm compiler (with a few flags to tweak the behavior to fit the asm.js semantics). In other words, if you're running asm.js in Firefox, you're literally just running wasm anyway, so how could it possibly be faster?
Furthermore, if you use wasm, you'll have fewer bounds checks (because of better memory allocation strategies[1]), access to SIMD, bulk memory operations, and a host of other niceties that have been added to wasm over the years. If your asm.js code is outperforming someone else's wasm code, that probably just means their wasm code is worse.
[1]: https://spidermonkey.dev/blog/2025/01/15/is-memory64-actuall...
yeah turns out it was chrome that was slow, not firefox.
wasm hashing in chrome is half the speed of firefox.
asmjs with optimizations enabled in firefox are about on par, which supports your statement.
https://theultdev.github.io/web-sha256-benchmark
Made the requested benchmark:
https://theultdev.github.io/web-sha256-benchmark
https://github.com/TheUltDev/web-sha256-benchmark
It's Chrome wasm (windows) that is slow for me, 2x slower than asmjs.
FF with asmjs optimizations are 2x slower than wasm on FF.
Wasm in FF is 2x faster than wasm in Chrome for this hashing solution (for me).
That is surprising. Do you know the reasons? Is it a special use case or was asm really faster? I find that hard to believe.
It's a custom solution, but nothing special just incremental hashing for large files.
I took off the shelf wasm crypto libraries to compare it, but the leading one was 10x slower.
can we see?
yeah check back at the end of the day.
will try to rip it out of the project and put it in a standalone benchmark.
It'd be interesting to compare it to a SHA-256 algorithm that uses Wasm simd: https://github.com/ChrisWhealy/wasm_sha256
Noted, will add that.
Last time I tried https://github.com/Daninet/hash-wasm
edit: I focus on browsers, that's wasm but not for browser envs.
----
https://theultdev.github.io/web-sha256-benchmark
https://github.com/TheUltDev/web-sha256-benchmark
seems it is chrome wasm that is slow.
asmjs is about the same speed in chrome and firefox (with asm optimizations still enabled) but wasm is slow as hell in chrome, asm still better.
side note: someone mentioned native crypto.subtle, but that doesn't have incremental hashing so can't use it for large files. however I do use it in practice for smaller files.
what's wrong with the built in one?
https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypt...
Requires a secure origin. If you serve a local (but non-localhost) SPA over HTTP then you're blocked from using crypto.subtle.digest. At least, that is one reason I have seen a hand-rolled SHA-256 deployed.
Edit: oh, and it forces async.
no incremental hashing, so you can't hash files too large for ram.
I do use it for smaller files though, it's much faster.
o7
asm.js is faster than WASM, and it can do everything that JS can do.
Congratulations, two spectacularly wrong 'facts' in one short sentence is quite an achievement ;)
It's true that in the beginning (around 2017), WASM wasn't much faster than asm.js, but meanwhile WASM has seen real performance improvements.
Featurewise, asm.js is much closer to WASM than to regular JS, it definitely cannot do everything that regular JS can do (mainly because asm.js is limited to the Number type, it cannot deal with JS strings or objects).
Faster in what browser, by what measure, for what modules? "X is faster than Y" without any concretization is usually meaningless.
How can a subset of JS do "everything" that JS can do?
All you need is a lambda
Faster? I'm not sure about that. Maybe if you are doing a lot of talk between the compiled and JS runtime/DOM. But otherwise WASM has been much further developed in both Firefox and Chrome.
I don't think Chrome ever did an asm.js specific optimization.
It did, V8 added asm.js compilation to WASM in 2017 https://v8.dev/blog/v8-release-61#asm.js-is-now-validated-an...
WASM wont improve if no one adopts it. Its a chicken and egg issue
WASM has been adopted and it has improved massively since 2017 though.
Yes, but GC is still useless for languages with interior pointers, some features require gimmicks with server configuration, and for most languages we aren't any way closer to -march=wasm and that's all.
We still need to download half Internet for emscripten, plus whatever tools are being used on top. Although it is somewhat simpler for those that build on top of binaren.