Jump to content

WebAssembly


Dal
 Share

Recommended Posts

A sort of philosophical question here...

 

I've been wondering about WebAssembly and how it might impact on us in the Javascript/WebGL world. 

http://www.2ality.com/2015/06/web-assembly.html

 

It seems when it's done, WebAssembly will make it fairly easy to port C++ and other language code to the web.

 

My question is: where do we think this will leave those of us who work with TypeScript/JavaScript and WebGL?

Will we be able to use this to complement our current technologies; e.g. by offloading some of the cpu intensive work to an optimised web assembly and better web workers whilst still benefiting from flexible javascript scripting? Or will we struggle to get real benefits from it as we do with asm.js/webworkers at the moment and therefore perhaps be outperformed by c++ ported engines that can be more optimised to use it?

I'd be interested to here some other people's opinions on that :)

 

 

Link to comment
Share on other sites

I did some asm.js tests beside BJS. The gain is real in term of speed within the asm.js process.

However, AFAIK, the only process that can access the DOM, so the canvas element and the webgl context, remains the main JS thread.

 

This means we have to pass the data from the main thread to the asm.js thread and get them back once computed. This is not a real problem, we do the same with the webworkers for instance and it works pretty well.

The problem is more than only ONE heap (buffer / shared memory between the two threads) can be passed. This heap can't have a dynamic size, and this size is generally a power of two and a multiple of 64. This is really low leveled.

If you need to pass to the fast asm.js thread, say for instance, a dynamic array of positions (vertex coordinates, so float32) and an array of indices (int32) at once to compute an array of normals (float32), this becomes really painful because you have to store in the same buffer float data, integer data, manage the pointers... and the same for the return.

 

In other terms, it's really really difficult to some javascript logic to communicate with some asm.js logic.

 

That's probably why the asm.js projects are coded from top to bottom in C/C++, then transpiled into asm.js : all the logic in the C/C++ code only.

The JS thread has then no logic at all, it only gives the access to the WebGL context.

 

So unless recoding the whole BJS library in C/C++ with a JS API and then transpile it to asm.js, I'm afraid it will be difficult to inject a little asm.js here or there to speed it up.

 

I didn't know about WebAssembly.

What about their plan about an emerging W3C recommandation what would the guarantee that every browser big editors would get involved into this ?

Link to comment
Share on other sites

@jerome From what I've read, I think WebAssembly already has the support from Google, Microsoft and Mozilla, so it looks likely to be a big player in the coming years.

 

What I'm wondering now, is whether it will make it easier for us to do the kind of stuff you're talking about... or whether it will still be the same problem, and we'll be at a speed disadvantage to c++ engines that are compiled for the web.

Link to comment
Share on other sites

My impression is that WebAssembly is being designed really just to make it easier for binaries from the C++ world to run well on the web.

It's really too early to tell whether JavaScript could benefit from transpiling to it.

If WebAssembly includes some features that optimize for functional language features, it may be good for JavaScript.

But we'll have to wait and see  :)

Link to comment
Share on other sites

I read much about this yesterday night.

 

As you may know, the current JS is compiled in the browser to a JS bytecode specifc to the browser JS virtual machine (V8 for chrome, Chakra for Edge, etc).

Because of the dynamic typing nature of JS, this compilation is mandatory done Just In Time (JIT).

The compiled typed languages like Java, also using the bytecode transformation from the source before behing compiled, can benefit from Ahead Of Time (AOT) compilation.

Actually, the AOT compilation is not the lone explanation about why the statically compiled programs can run faster than the dynamically typed ones. Indeed, a Java program will run faster even JIT compiled than any dynamically JIT compiled program.

Why ?

 

You guess it : because of dynamic typing. 

The compiler and the VM have many type checks to do at run time, because behind every type used many dynamic memory allocations (and de-allocation) and pointer managements happen under the hood.

 

WebAssembly is a project that intends to provide a binary format and a common bytecode to the Web. 

This will allow to download directly the bytecode from the website, instead of the JS source then to be locally compiled, so less bandwidth, more speed to start to run.

This will allow also to get close to native speed at execution time. 

Because this bytecode will use fixed types.

 

For now you can ever choose a statically typed language or a dynamically typed one, then compile it (JIT for dynamic ones) to a given bytecode if you have the right compiler.

 

Let's get back to Javascript.

Javascript is dynamically typed. This means that we can't better that what is currently done : JIT compilation to the dedicated VM bytecode.

WebAssembly will just be something beside JS.

 

How developers will emit WebAssembly ? Well, the source languages, for now, are just C/C++ (so statically typed).

You code in C/C++, you inject your source into a big chain of complex tools and you get your wasm code that will run in the browser at almost native speed ... once the browser will have the WASM VM.

 

Let's now consider TypeScript.

For now TypeScript just transpile to JS after have done all type checks. In other words, TypeScript checks types but emit a not-statically typed language, JS, the lone currently able to run in the browser. 

The source has the static type, the target lost them.

 

Now let's imagine that TypeScript would be more strongly typed.

 

For instance :

var i: number = 10;var x: number = 2.9864;

would become instead

var i: int32 = 10;var x: float64 = 2.9864;

I personnaly wouldn't mind to code with stonger types once I accepted to use a statically typed language.

 

This means that with a little TypeScript syntax modification (let's call this version StrongTypeScript) we could afford the possibility to get a source language potentially directly compilable to WebAssembly !

And still transpilable to legacy JS !

 

StrongTypeScript = transpile (TS) => JS

StrongTypeScript = compile => wasm bytecode ... once this compiler will exist, but realisable because of the strong static typing nature of StrongTypeScript, java-like, c-like, etc

 

As BJS is coded in TS, this would be only a little fix (just add the missing types to the local temporary variables missing them within some methods) to get the whole framework potentially compilable to the upcoming WebAssembly.

 

So, people here working at MS, please contact your colleagues from TypeScript and invite them to add this stronger typing feature to the language  ;)

 

thank you

Link to comment
Share on other sites

I think you'd have more chance if you argued that additional numeric types would be useful in Typescript even if it doesn't target WebAssembly*... (I've read their bug tracker for suggestions like outputting JSDoc comments so the output of the transpiler can be put through the Closure Compiler, I get the feeling they won't go for a change that is outside of their vision for the direction of the tooling)

Javascript already supports more than just "number", today, we have typed arrays which let as explicitly store various sizes of integers and can store single precision floats in addition to doubles. It also looks like Math.fround() will be supported (soon, apparently Unity jumped the gun and are suffering for trying to use it too early) as a hint to the browser that it can do faster single precision maths(eg. Maths.fround(Math.sin(x)) should do do a single precision calculation of the sine of x). Browsers do already make use of hints that an expression will only ever be an integer, with the Chrome devs notably trying to offer explanation of how this works in their browser ( var i=j|0; //browser's JIT should know that i can only be an int, if it already know j is int the "|0" should be a noop )

All this is to say that I feel Typescript would be better with more numeric types even targetting only transpilation to JS, their is already room to support these even only compiling to Javascript I think.

*my hunch is that building a decent TS to bytecode compiler would also be an awful lot of work

 

 

EDIT: It seems to be old and like it hasn't been updated in a while, but what about LLJS as a possible way Babylon.js could exploit typing for speed (disclaimer I just happened upon it by chance recently, I have not played with it)

Link to comment
Share on other sites

Interesting stuff... that seems like a natural evolution for typescript to me - and then Babylon could run much faster with minimal changes.

 

I wonder whether we could also benefit from a "hybrid" though? Do you think it will be possible to rewrite just the performance-hungry bits in c++/webassembly and keep the rest of the engine in javascript?

Link to comment
Share on other sites

I suppose (couldn't find any detailed specs about this, in particular about the DOM access) that the pipeline between the browser main JS thread and the compiled thread beside (they are always set in different context for safety reasons) will be the same as for the current asm.js model.

It is to say a shared low level single memory buffer.

 

This wouldn't be convenient to keep the engine logic in the JS part and to delegate only some computations to the compiled thread.

I guess the right architecture would rather be :

- a minimal JS main thread having the access to the DOM, so to the WebGL API, to handle the UI events and the GPU calls

- a complete compiled 3D engine (would be nice to be coded in TS) exposing a JS API so the users could code their own game logic in JS and passing the computed orders of rendering to the main thread

 

The user logic would then be coded in the main JS thread as currently

 

Nothing prevents the downloaded bytecode from being the main thread code (so having the access to the DOM) afaik, so the  compiled full engine could be in the main thred code , but in this case, I can't imagine how/where the framework users would code their logic in javascript.

Link to comment
Share on other sites

Nothing prevents you from sharing the main thread cooperatively, at least with asm.js (probably with WebAssembly too but I haven't checked).

The issue with interop is still overhead and hassle from what I've been able to figure out... how ugly and unmaintainable should one consider making code in the name of a small performance boost. Right now there isn't any tooling on the JS side that let's you work with the typed array views of the buffer "nicely" (ie. your JS code is all manual computed offsets into the buffer to read or store data in the C/C++ accessible "memory", maybe that LLJS would have addressed this if it wasn't abandoned/is one day resurrected).

You can access JS objects in C/C++ now with minimal overhead (I think) but I suspect the more JS objects you work with the less advantage you gain (AOT is still specific to Firefox I believe, and I think only really saves you from the few seconds of warmup as JS code is initially executed by the interpreter, and it's the memory access that makes C++ properties and structs potentially faster)

Link to comment
Share on other sites

I was too quick to judge the performance of that demo, it is doing way more calculation than I gave it credit for, at 600 objects it's calculating gravitational attraction between something like 359400 pairs of bodies. I'd guess inlining may help but yeah I was judging it based upon looks, and looks can be deceiving.

Link to comment
Share on other sites

  • 3 months later...
  • 8 months later...
  • 6 months later...
  • 2 years later...

Hi,

I will be grateful if you answer my question about postMessage for WebAssembly.
I want to implement a counter code that have 2 main parts:
1. A Counter worker that continuously increment the WebAssembly.Memory as a counter variable,
2. The main code that reads the counter value from counter thread whenever it wants.
I want to implement this code using a web worker and postMessage for passing the value of counter. The WebAssembly.Memory is the container of the counter and is defined in the main code and is being increasing in the counter worker. 
In fact I want to use WebAssembly.Memory like SharedArrayBuffer.
My question is: how to implement the  worker part of code and to increment the counter in JS and then read it in the main code? In fact I don't want to use multithreading in WASM, but I just want to implement my goal in Javascript, because I believe today multithreading is just a beta version and is in fact multi-tasking not multithreading. And it is not possible to run 2 threads completely simultaneously.
Thanks a lot.
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...