The performance bottlenecks I mostly see as a frontend engineer are those related to the browser (execution speed, DOM manipulation, and painting). I'm curious what workloads wasm can improve, since I assume it'll mostly deal with operations in memory. Maybe physics or graphics calculations in JS game engines?
Those where you have a significant amount of computation. Image/audio/video processing, neural networks, text analysis, games fall there too. Generally, those things are not done in the browser currently, but wasm will change that, so I'd say it will rather open new doors then fix existing ones.
JavaScript as a language also doesn't make a lot of guarantees. Dynamic languages are great for small projects, but I think we've very clearly seen from the growing interest in linter tools and gradual type systems like TypeScript and Flow that there is huge interest in having more static guarantees. Compiling to WebAssembly has the added benefit of letting you work in a language that has them already, rather than having to shoehorn them into a language that wasn't ever designed for it. And if we are going to have a translation step regardless (ES2016 to ES5), then why not start with something better than ES2016?
I hear this a lot from people who have little or experience building large applications in high level languages. If you manage your code properly you can have strong/static typing in JavaScript. The difference is that nothing yells at you when you mess that up. Instead the application just runs a little bit slower.
I have written large parsers and code beautifiers in JavaScript that blow the shit out of anything I have seen written in other low level languages. There are a couple of advantages that JavaScript provides for this.
First of all you get immediate execution without a separate build or compile step. You can see that execution (on really large applications) is a bit slower the first time due to JIT compilation, but successive executions are faster because the code is already compiled in memory.
Secondly JavaScript runs almost everywhere. I don't need a special run time or execution context. I can run JS apps on the command line or browser without having to push data to a server location and await a response.
Finally, JavaScript is fast now. It executes almost as fast as Java and is only about 4x-8x slower than C++.
The biggest limitation I have found with JavaScript is memory management. Trying to parse a 180mb (or larger) XML file in my JavaScript application can result in an application crash due to excess memory requirements.
> I hear this a lot from people who have little or experience building large applications in high level languages. If you manage your code properly you can have strong/static typing in JavaScript.
No, you can't. If you manage your code properly, you can have code without the kind of errors that would be prevented by static typing, but JavaScript does not have static typing, period. (I mean, you can have it via type annotations in comments and a separate static analyzer, but that's a type language on top of JS, not JS proper.)
> The difference is that nothing yells at you when you mess that up.
Which means you don't have static typing; static typing is when the types are statically verified prior to runtime, and something does yell at you when they are wrong.
> Instead the application just runs a little bit slower.
Performance problems are the least issue with uncaught type errors. Crashes and incorrect results are the more common results.
Just a small point: machine code/assembler has limited typing too, but that doesn't mean we say that Haskell isn't strongly typed.
Using any number of languages that compile to javascript can give you just as strong typing in js as in any language.
(I will grant you that you technically don't "get" strong typing in js, but rather in the language above it - but for practical purposes, you can have a language quite like js, with "actual" strong typing).
If, in an application, all your references are of a single data type and those data types never change the types in that application are static. This remains true even though the language is not statically typed. The language may be dynamically typed but all data types are static at execution, which is what static typing is.
Also don't confuse static/dynamic type classifications for strong/weak type classifications.
> Performance problems are the least issue with uncaught type errors. Crashes and incorrect results are the more common results.
The idea that dynamic languages are OK for small projects but static languages are needed for big ones isn't valid.
Static languages don't solve the kinds of problems large projects have over small projects.
Static code analysis has its place, but it makes awfully weak guarantees itself. Can you ship a product because you got it to compile?
Larger projects of any stripe will want unit tests and other automated tests to ensure it does what it is intended to do. They're also usually going to want linters and other tools to enforce policies.
I think when you compare where you are with:
1. static language + linters + decent automated test coverage
2. dynamic language + linters + decent automated test coverage
While the DOM may always be slow, faster JS (ie. wasm) can provide faster calculations in pure javascript land and better efficiency (better memory management, similar to c++/native stacks).
This is useful for optimizing DOM usage, such as using a virtual dom to avoid excessive real DOM access.
So while it does not attack the bottle necks directly, it will increase the overal perceivable performance of a webapp.
Once there are wasm native APIs you'll be able to do everything without touching Javascript at all, so it can improve all workloads.
Some may not get a lot of improvement, if the bottleneck is in the browser engine, e.g. DOM manipulation. But there are many where the browser engine doesn't really do much - OpenGL, audio, any internal computation, etc.
Wasm operates using the same VM as JavaScript in the browsers currently supporting it. At this time it is nothing more than a compute optimized subset of JavaScript
Actually WASM as it is right now will not help significantly with any of that. The main issue with javascript is that it is a script, so it has to be compiled before it can be run. Therefore, for decent sized scripts, it can take up to 1-3 seconds to actually parse the damn thing. With WASM, you can send up compiled code which will reduce that initial load time.
If you tried to implement OpenGL in WASM, it would be incredibly slow and take a long time to load. You will always be constrained by the browser painting the DOM, or changing canvas, whatever. You can't display info to the user from javascript without modifying the DOM.
> I don't think Go works with WASM, because it uses a GC.
So? To WASM, how is the GC different from manual allocation, since it's just explicit manual allocation/deallocation in the underlying runtime that gets compiled to WASM.
From what I understand, the WebAssembly team is working on their own GC and the Go team would like to use that rather than rolling their own for this target. Also, WebAssembly doesn't have threads yet, which is pretty important for Go.
In short, Go in WASM isn't there yet, but it is most likely coming at some point. I expect most popular languages will be ported to WebAssembly at some point, but IMHO Go itself is far more suited to running backend services than in the browser.
This seems like there could be even more stuff automated.
Because Rust is statically typed, a rust-loader could "overload" import() so it initialises and extracts the exported/non-mangled function signatures and create the JS equivalents automatically.
Sure. But I think a better way would be a separate build tool and step, which generates the javascript proxy functions. With that way you get code completions and type checking for the remaining javascript/typescript, if the loader does everything dynamically you are more likely dynamically typed.
Cool to see more people digging into Rust + Emscripten.
Not sure why the guide is using nightly Rust, stable has worked pretty well on Emscripten for a while. If you need to pass custom linker flags(which emscripten sometimes requires) you can do it via rustflag directive in .cargo/config.
We've been using Rust + Emscripten for some cross-platfrom targets(web, win32, osx, android and linux) and been pleasantly surprised with how straightforward+stable it's been.
It's in a bit of a transition; we're planning on using LLVM's backed for wasm, and I believe that's landed in nightly[1]. Stable has support but through emscripten's LLVM patches. So maybe they wanted to try out the new stuff, or maybe they didn't know that it was on stable already.
Hi, author here. Thanks for the tip, I wasn't aware compiling with Emscripten would work on stable. That should simplify the process. I'll do some more research and update the guide.
Yeah, was a great article, kudos for that. To be clear I didn't mean it as a criticism just wanted to throw it out there so other people knew that it works on stable.
The most popular JavaScript engines do indeed have real integers available. You can get real Integers in regular JavaScript, they are just cumbersome. But if you're transpiling, you can hide that difficulty away.
IEEE 754 double precision floats have enough precision to represent every 32 bit integer, the problem is when you try to use them to represent 64 bit integers, you get problems such as this: https://github.com/nodejs/node/issues/12115
Author here. It is my cursory understanding that the Emscripten SDK handles converting types to and from Javascript values and C-like data in the module's virtual memory. I'm not totally sure how that conversion is happening yet. I can tell you that when I pass a string when it expects an i32, it treats it as 0, so `add("foo", "bar") -> 0`
I was surprised to see the author describe Rust-in-the-browser as "low level". I always took that term to mean "closer to the metal", and not statically typed with manual memory management. Rust in this context doesn't seem any more low level than Javascript, to me.
Web Assembly (and also asm.js) are "closer to the metal" even though they run in the browser. The execution model is meant to map pretty closely to assembly, not to JavaScript. The browser is supposed to be doing static verification for security purposes, but not much in the way of optimization.
WASM is way lower-level than JS. It doesn't have functions as objects, or really any object system. And the point is for developers to write higher-level web languages that compile down to WASM, so there's no real pressure to add layers of abstraction down at this level. https://medium.com/javascript-scene/what-is-webassembly-the-... It seems like you're hung up on the "browser" part, but it's just providing a compiler and a sandbox.
I have the horrible feeling that the main applications of WebAssembly will be hostile code. Ads, malware, spyware, paywalls, and other junk. Look at the history of Java in the browser, and Flash in the browser. 2% great, 98% terrible.
Consider WebGL, which is very impressive yet seldom used. There are some very nice demos, most of them several years old, and some half-finished indy games. Other than that, not much. Kind of like VRML.
Browsers need a "disable WebAssembly" option. It should require user interaction to turn it on.
> Consider WebGL, which is very impressive yet seldom used.
I want to like it, and do confess it is nice way to prototype shaders.
Yet thanks to the way it works, blacklisting GPUs, it means all my mobile devices are OpenGL ES 3.x capable and yet they can hardly display many WebGL pages.
While most games just work.
Regular users won't be going into browser settings to enable WebGL content, 99% of them won't even know such configuration does exist.
I agree this should be a major concern. How is an adblocker or tracker blocker going to work when the malicious ad is compiled? It might not be able to access your machine, but it can drain your battery and deliver malware through security flaws.
43 comments
[ 118 ms ] story [ 1349 ms ] threadThose where you have a significant amount of computation. Image/audio/video processing, neural networks, text analysis, games fall there too. Generally, those things are not done in the browser currently, but wasm will change that, so I'd say it will rather open new doors then fix existing ones.
I have written large parsers and code beautifiers in JavaScript that blow the shit out of anything I have seen written in other low level languages. There are a couple of advantages that JavaScript provides for this.
First of all you get immediate execution without a separate build or compile step. You can see that execution (on really large applications) is a bit slower the first time due to JIT compilation, but successive executions are faster because the code is already compiled in memory.
Secondly JavaScript runs almost everywhere. I don't need a special run time or execution context. I can run JS apps on the command line or browser without having to push data to a server location and await a response.
Finally, JavaScript is fast now. It executes almost as fast as Java and is only about 4x-8x slower than C++.
http://benchmarksgame.alioth.debian.org/u64q/compare.php?lan...
The biggest limitation I have found with JavaScript is memory management. Trying to parse a 180mb (or larger) XML file in my JavaScript application can result in an application crash due to excess memory requirements.
No, you can't. If you manage your code properly, you can have code without the kind of errors that would be prevented by static typing, but JavaScript does not have static typing, period. (I mean, you can have it via type annotations in comments and a separate static analyzer, but that's a type language on top of JS, not JS proper.)
> The difference is that nothing yells at you when you mess that up.
Which means you don't have static typing; static typing is when the types are statically verified prior to runtime, and something does yell at you when they are wrong.
> Instead the application just runs a little bit slower.
Performance problems are the least issue with uncaught type errors. Crashes and incorrect results are the more common results.
Using any number of languages that compile to javascript can give you just as strong typing in js as in any language.
(I will grant you that you technically don't "get" strong typing in js, but rather in the language above it - but for practical purposes, you can have a language quite like js, with "actual" strong typing).
If, in an application, all your references are of a single data type and those data types never change the types in that application are static. This remains true even though the language is not statically typed. The language may be dynamically typed but all data types are static at execution, which is what static typing is.
Also don't confuse static/dynamic type classifications for strong/weak type classifications.
> Performance problems are the least issue with uncaught type errors. Crashes and incorrect results are the more common results.
Absolutely not in this language.
Static languages don't solve the kinds of problems large projects have over small projects.
Static code analysis has its place, but it makes awfully weak guarantees itself. Can you ship a product because you got it to compile?
Larger projects of any stripe will want unit tests and other automated tests to ensure it does what it is intended to do. They're also usually going to want linters and other tools to enforce policies.
I think when you compare where you are with:
1. static language + linters + decent automated test coverage
2. dynamic language + linters + decent automated test coverage
you are in the same place.
This is useful for optimizing DOM usage, such as using a virtual dom to avoid excessive real DOM access.
So while it does not attack the bottle necks directly, it will increase the overal perceivable performance of a webapp.
Some may not get a lot of improvement, if the bottleneck is in the browser engine, e.g. DOM manipulation. But there are many where the browser engine doesn't really do much - OpenGL, audio, any internal computation, etc.
If you tried to implement OpenGL in WASM, it would be incredibly slow and take a long time to load. You will always be constrained by the browser painting the DOM, or changing canvas, whatever. You can't display info to the user from javascript without modifying the DOM.
The Haskell crowd seemed to think that was how it would work for them: https://www.reddit.com/r/haskell/comments/5ydqrc/compiling_t...
So? To WASM, how is the GC different from manual allocation, since it's just explicit manual allocation/deallocation in the underlying runtime that gets compiled to WASM.
From what I understand, the WebAssembly team is working on their own GC and the Go team would like to use that rather than rolling their own for this target. Also, WebAssembly doesn't have threads yet, which is pretty important for Go.
In short, Go in WASM isn't there yet, but it is most likely coming at some point. I expect most popular languages will be ported to WebAssembly at some point, but IMHO Go itself is far more suited to running backend services than in the browser.
This seems like there could be even more stuff automated.
Because Rust is statically typed, a rust-loader could "overload" import() so it initialises and extracts the exported/non-mangled function signatures and create the JS equivalents automatically.
Not sure why the guide is using nightly Rust, stable has worked pretty well on Emscripten for a while. If you need to pass custom linker flags(which emscripten sometimes requires) you can do it via rustflag directive in .cargo/config.
We've been using Rust + Emscripten for some cross-platfrom targets(web, win32, osx, android and linux) and been pleasantly surprised with how straightforward+stable it's been.
1: EDIT: looks like it https://github.com/rust-lang/rust/pull/42571
Consider WebGL, which is very impressive yet seldom used. There are some very nice demos, most of them several years old, and some half-finished indy games. Other than that, not much. Kind of like VRML.
Browsers need a "disable WebAssembly" option. It should require user interaction to turn it on.
I want to like it, and do confess it is nice way to prototype shaders.
Yet thanks to the way it works, blacklisting GPUs, it means all my mobile devices are OpenGL ES 3.x capable and yet they can hardly display many WebGL pages.
While most games just work.
Regular users won't be going into browser settings to enable WebGL content, 99% of them won't even know such configuration does exist.