32 comments

[ 3.3 ms ] story [ 78.4 ms ] thread
Where is the performance data?
I recall a recent blog post by Mozilla where they said they removed most of the overhead in JS <-> WASM.

I agree, without data, the observations cannot be replicated or discussed. I'm sure there's a simple explanation for each point.

This right here.

I'm taking his results with a pound of salt. There's no detail, so the experiment cannot be reproduced by a third party. Where's the scripts and WASM programs used for testing so that others can verify not just the results, but that the WASM and JavaScript programs were actually comparable.

Yeah, and it also doesn't go into questions like what kind of tasks the code performs. For example, if it is constantly copying huge arrays back and forth the bottleneck is memory, not computation.
This is short-sighted enough to border on shit-posting.

So the only thing people want to do with WASM is deploy C/C++ to the browser and for raw speed?

There's many other reasons you would want to use WASM...you might want to use languages with better tooling or better suited to the purpose of your code (I'd rather do UIs in Lua than JS 10 times out of 10). Maybe you want a tiny memory footprint so you can run on small devices. The list goes on.

Those are the two main things it's currently suitable for. People who haven't looked at it have too crazy expectations for it. It's not some magic run all languages thing like GraalVM/Truffle it gives you a way to run a restricted subset of machine instructions.
I'd be extremely careful calling a computer science professor's opinion shit-posting. He's basing his argument on end-user experience. You, on the other hand, are giving dev-experience more weightage. Depending on what you want, WASM may or may not be useful.
For a scientist, he does a piss-poor job of producing open, reproducible research. He doesn't even show numbers. Whatever his credentials may be, this post is all talk without even a nugget of actual data or information. So yes, it borders on shit-posting. We have to expect better from a CS professor
Yeah - in a way it's worse that the article is so lacking in detail because you expect the evidence to be present as a base-line level of competency for a person with such a position. We certainly shouldn't be appealing to authority, at any rate.
Just because someone has a respectable credential or title does not mean that they don't like to troll sometimes, or worse (nb: no accusations are being made here), have a vested interest in opposition.

People, for reasons we don't know, understand or maybe without reason at all, put their professional reputations on the line all the time. Most of the time it goes by unnoticed.

But a lot of other languages with better tooling et al just choose to compile to JavaScript. It's not like you need WASM for that.
But why use JavaScript engine as the “base”? Why not a more “general” VM?

WASM just skips the JS to JIT compiled bytecode - correct me if I’m wrong. Creating a standardized bytecode for distribution that other languages can compile to.

No reason to continue to shackle the web to JavaScript.

I'm no expert, but I think one issue is the lack of a GC in WASM. So each language have to roll their own custom GC on top of it.

Another reason is JS already has many high level features. Which might make it easier to implement similar ones in your language if you target JS directly.

The last reason I can think of is interop with existing JS code and the DOM.

A GC for wasm is planned, as is DOM/browser API interop.
These things are on the roadmap atm.

Better WASM/JS interop is on the way, though atleast on Firefox nightly you can get this for fairly low cost for some functions.

GC is also on the todo list and IIRC might get an early preview in Firefox Nightly.

Once the GC is done, DOM integration will happen, people are eager for that and that would eliminate a lot of the necessary JS glue code.

(comment deleted)
I don't believe this, but it's an understandable error.

First, let me be clear that handwritten optimized WASM is faster and smaller than heavily optimized Javascript on primitive types, by significant margins. It doesn't surprise me that compilers burn this (to put it mildly, compilers aren't great at code generation), but it's worth noting that the raw throughput difference is there and definitely measurable. This difference should be expected to grow in the near future, since browsers' WASM compilers are suboptimal right now.

Now, more importantly, the major criticism I have with this is that it is presumably focused on small imperative tasks, which ignores the main places performance is lost in a language like Javascript:

1. Javascript can't handle memory efficiently without doing everything through typed arrays. Efficient use of memory (compact representations, mutation and sharing, sequential access, etc.) is an unreasonable task in a high level language, whereas transpiling to WASM works.

2. Javascript's abstractions are heavy and inefficient. Building your own abstractions is liable to have similar issues. A language like C, C++, or Rust lets you build efficient abstractions both in the small ("zero-cost abstractions") and in the large (architecturally).

Little unpublished demos won't show that.

WASM is basically the formalisation of asm.js. Therefore writing javascript code that rivals WASM is possible by definition but writing fast Rust/C++ code is much easier than trying to do the same with javascript (it won't look like javascript).
asm.js is not "just" efficient Javascript though. It is typically compiled a different way to standard JS.
Not that I disagree with you but we might need to have more discussions about what is a common/normal app. How large is it in kb, in lines of code, in nbr of functions or classes? How large and how many data structures is it normally using?

Without this it is hard to say if any language will help. WASM is probably faster and if cross language calls don't cost anything extra (Firefox seems have solved most of this) a combination of WASM and js shouldn't be slower than a pure js solution but if the applications isn't _that_ large and doesn't use too many data structures it might not be much faster either.

It's still early days for wasm. Rust has great support for wasm, and I predict it's going to be a leader in the space, but wasm isn't there yet. Javascript has been optimized for decades now, and it's been a critical technology for a lot of companies with deep pockets. As wasm gets better and adoption grows, we'll see it improve drastically.
With Microsoft making moves like blazor, you may see a huge shift into .net devs bukidng with web assembly.
I'm getting the opposite results from my work with WebAssembly (https://floooh.github.com/tiny8bit, https://floooh.github.io/sokol-html5/, https://floooh.github.io/oryol/).

As for the size vs JS: this depends a lot on the language used to compile to WASM, rule-of-thumb: the higher level the language, the more complicated it is to keep the size down. But if you use an 'embedded style' of C, it is quite trivial to keep the size below even compressed Javascript code that does the same, as long as the Javascript code isn't just glueing together a few HTML5 APIs and the DOM.

Some of my findings:

- https://floooh.github.io/2018/05/01/cpp-to-c-size-reduction....

- https://floooh.github.io/2016/08/27/asmjs-diet.html

As for performance: you need to show the code and benchmark results since JS being faster than WASM is against what most people who actually worked with both are seeing. It's definitely possible that badly written C code compiled to WASM is slower than well written JS code, but that takes a lot of effort ;)

WASM allows control over the memory layout that's just not possible with "idiomatic" JS, unless throwing most of Javascript's convenience away and directly poke into ArrayBuffers.

One reason why JS could be faster than WASM is (or rather was) when the WASM code needs to do a lot of calls into JS, but this has recently been addressed in Firefox (and other browsers hopefully follow soon).

Some more info on why WASM is faster then "idiomatic JS":

https://floooh.github.io/2017/06/09/webassembly-demystified....

Wow, nice demos! You got yourself a new Github follower.

Out of curiosity, because you seem to focus on 3D graphics or really old-school emulation: have you given any thought in how WASM might be beneficial for rendering 2D graphics? What would you expect to be the best approach to squeeze more performance out of that use-case?

I think 2D graphics is also mainly a WebGL problem. Fill a vertex buffer with 2D vertices each frame, and try to render it with as few draw calls as possible (e.g. fill vertices sorted by texture, and only issue a new draw call when the texture changes, pack small textures into a bigger texture atlas etc...). Most what makes this fast is how WebGL is used and can be done quite efficiently from JS too. WASM may help in the tight loop where the vertex buffer is filled with data though.
Prove it. I don't believe you, and you haven't posted any data. Try compiling some computationally intensive code with wasm-pack (and rust) and run it against an idiomatic javascript version. The Rust/wasm version will be faster, smaller, more efficient.

If you're compiling the C code with emscripten into a asmjs or something, then of course it's going to be bigger and slower.

But again, without a shred of proof, we have no way to know.

After compression, asmjs and wasm come out at about the same size (give or take 5% or so), wasm is also about the same speed as asmjs (unless you need a lot of 64-bit integer operations, or you're running the asmjs on iOS Safari which doesn't seem to have any special handling for asmjs).

Also, C via emscripten vs Rust via the LLVM wasm backend shouldn't make much of a difference as long as you don't need to use emscripten's browser shims (you can compile 'naked' WASM without any C or JS runtime in emscripten too).

Here's a list of reasons wasm can be slower or faster:

Faster:

1. Compiled to a strongly typed IR, wasm code means just one thing. For instance i32.add means addition of 2 i32s. In JavaScript a '+' operator has some 70 different possible input parameters. Hence, the engine cannot assume the types (until a later optimization stage) during execution

2. 'JS -> AST -> machine code' is a typical sequence for js execution. In contrast, for wasm it is 'wasm->machine code'

3. For medium to large code bases, wasm's binary format is more compact than a js text format. Wasm can also be gzipped for further compression. It should lead to smaller downloads over the wire in such cases.

Slower:

1. Passing data to and from wasm needs to happen on it's heap. Oftentimes, this is a non zero-copy operation of a JavaScript object onto the heap, and back. This can lead to preformance bottlenecks

2. The actual calling interface between wasm and js incurs a cost. If the rate of calling across this interface exceeds time spent within the wasm, performance degrades. Think CPU<-->GPU where the invocation and dates passing between the interface exceeds compute time on GPU

3. Wasm doesn't have access to Dom, network, storage, .... If your app uses these from within wasm, it's essentially calling back and forth to js while stalling wasm execution and incurring high costs to navigate the wasm<-->js interface.

There are plenty of samples available online demonstrating the above points. A simple demo is that of a fibonacci series for a large number. As the number gets larger, wasm starts to easily outperform js