Remix.run Logo
tardedmeme 20 days ago

What are the key differences between PNaCl and WASM?

flohofwoe 20 days ago | parent | next [-]

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

andrewl-hn 20 days ago | parent | next [-]

> Alchemy

Yep, that's the name. There was a brief period in late 2000s when Adobe was pushing hard to make Flash embedded into web ecosystem. They made Air as a way to package Web or Flash code into a desktop app. Essentially it was Electron-before-Electron. Alchemy was a part of this grand plan to be able to integrate existing native libraries with Flash code. The plan was like you said to compile to Flash bytecode, and AFAIK it never went further than a tech demo.

This whole ecosystem turned into a slow train-wreck over approximately 5-year period. Adobe really saw themselves as future stewards of web technology. They donated their ActionScript VM and a JIT to Mozilla and hoped that Firefox would become the first browser with fast JavaScript engine. Google developed Chrome and V8 in secret and managed to release their fast browser early. Microsoft and Yahoo sabotaged adoption of ActionScript dialect as at the next JavaScript. And at the same time Apple went fully anti-plugins, and with the rise of iPhone both Flash and silverlight died off.

Years later Java folks tried to build their own version of Alchemy as part of GraalVM. The project was called Sulong and was using Graal to execute and JIT LLMV bitcode. TruffleRuby was supposed to be a primary early beneficiary to be able to compile and run Ruby native extensions. This was during the period of a race between several JIT solutions in hopes to become "the next Ruby", and Truffle team (along with IBM's OMR) lost the race first to MJIT and then to YJIT. Graal itself seems to loosing steam, because their multi-language VM never got enough adoption among Java, Node, or Ruby people, and the VM itself tended to use too much RAM in era when RAM became premium in the cloud.

pjmlp 20 days ago | parent [-]

Graal was never designed as OpenJDK replacement, it is the evolution of MaximeVM, and their main customers, meaning who pays the team salaries are the Oracle database and cloud teams.

In that regard they are doing pretty well.

Plus all the folks that never paid for ExcelsiorJET, JRockit, PTC, Aicas, and many others of which only PTC and Aicas survive, now have in Graal their gratis AOT compiler.

Alongside OpenJ9 (which is more like what Leyden is trying to be), and the one on the box shipped alongside ART.

Ruby on top of JVM has a few interwined stories since the days Sun embraced it on Netbeans, and it suffers from the same issues as PyPy regarding adoption, it suffices not to be 100% compatible with whatever crazy extensions written in C exist out there.

Microsoft was probably more clever giving up on IronPython and IronRuby, and keeping the DLR infrastructure.

p_l 19 days ago | parent [-]

In my experience JRuby is way more viable than Jython ever was, one because Ruby native modules were more often thin wrappers, two because Ruby has sorta-standard in form of test suite (which AFAIK evolved from one that was necessary for ISO Ruby effort), and established somewhat case of using different implementations..

And C extensions never got as crazy as in python, and some major ones either made Java backends or switched from MRI embedding to FFI

bawolff 20 days ago | parent | prev | next [-]

> 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 (?)

flohofwoe 20 days ago | parent [-]

Indeed, NaCl and PNaCl would have been hit by Meltdown/Spectre at least as badly as SharedArrayBuffer.

kg 20 days ago | parent [-]

I remember early during the Wasm design process we were openly speculating whether people would eventually figure out how to do stuff like Rowhammer from raw Javascript. My bet was on Yes, but I don't remember if any of my teammates said No. I think we all knew the writing was on the wall by then.

Randomno 20 days ago | parent | prev | next [-]

> (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/

Yoric 20 days ago | parent [-]

Wasn't pepper the P in PNaCl?

Randomno 20 days ago | parent [-]

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.

jcranmer 20 days ago | parent [-]

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.

pjmlp 20 days ago | parent [-]

Now you can have all of them running on top of WebAssembly, companies even pay for support.

xg15 20 days ago | parent | prev | next [-]

> 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).

Out of curiosity, does that mean that NaCL (without P) only ran on x86? Or were there different subsets for different architectures?

wffurr 20 days ago | parent | next [-]

You could compile NaCL code for x86_64, aarch64, and aarch32 as well. Chrome apps has a system similar to mobile apps where you would upload an app with all binaries and users would get the one for their system architecture.

xg15 20 days ago | parent [-]

Ah, that makes sense. So users were effectively cross-compiling the NaCL binaries for multiple architectures.

wmf 20 days ago | parent | prev [-]

I think the plan was to JIT x86 to other architectures.

jorvi 20 days ago | parent | prev [-]

Heh, emscripten. I remember running the Unreal engine in the browser with that. Quite impressive indeed.

mccr8 20 days ago | parent | prev [-]

One of the big issues with NaCl is that the API it used wasn't standardized at all and there was only a single implementation. You could pick a random function and ask "hey, what happens if you pass in some slightly weird arguments?" and there was no answer beyond "whatever Chrome does". With enough work, maybe that could have been overcome while preserving backwards compatibility, but there were lots of random functions in there because somebody or other had found it useful. WASM was built from the ground up with a standards process and multiple implementations.