Saturday, June 27, 2015

Universal web code | Part 1

This article illuminates modern tendencies in creation of universal web assembly code. Java-Script seems to be a winner in a Web rivalry with values of popularity, simplicity and universality nowadays.


Douglas Crockford, famous Java-Script community contributor, in one of his presentations takes fun on the history of staging Java-Script, it is worth to see. The language itself has its own style, known as "Sex & Drugs & Rock & Roll": do some magic as you want, but be very, very cautious (more at weird syntax and dynamic nature)

alert('' == '0'); //false
alert(0 == ''); // true 
alert(0 =='0'); // true    
Browsers (written C++) parse Java-Script code and try their best to emit machine commands. Their best were not so good for a decade, and Java-Script has a reputation as very, very slow language (though the problem is not only in the language itself).

Lars Bak made a revolution in 2012 for Google Chrome V8 engine. He applied an idea of JIT compilation to the browser. This is very similar to Java and to .NET engines workflow, or in simplified form:
Parse java-script -> Abstract Syntax Tree -> ByteCode [Compile time] -> JIT [Execution time]-> Machine Code.
Optimisation in byte code step and machine code step drastically increased performance.
The same approach were taken by other browser vendors: Firefox with TraceMonkey, Safari with Nitro engine and Microsoft with JScript engine (now Chakra).

Alright, now we have the universal programming language with a good performance, hooray. Hold your horses, there is another problem with performance, it is much better now but still 10x's times slower  in comparison to a native client code.

Web browser engines have a problem in optimisation of Java-Script due to its dynamism.
Engine prepares batch of instruction for a processor at byte code compilation. Then at execution time (running JIT) it checks how good was prediction, if there is a change then engine should invalidate command tree and start process again. The invalidation problem is called "bailout". For example engines do not optimise part that has with() statement.

function containsWith() {
    return 0;
    with({}) {}


David Herman (Senior Researcher at Mozilla Research) has been contributing to asm.js project. Firefox team had an idea to make a restricted subset of Java-Script that provides only strictly-typed integers, floats, arithmetic, function calls, and heap accesses. This approach is closer to C/C++ programming and when browser meets ams.js hint the engine can better optimise code and finally get less bailouts.
The idea of transferring "favourite" language to Java-Script is not new itself, Microsoft started conversion of .NET code to JS in ASP.NET classic with ViewStates and Google developer has ScriptSharp project, Google converts Java to JS with GWT , Python has PyJs project. The difference in universality, asm.js is purposed to be universal assembly alike language.

At first step you can write code in statically-typed variant (C/C++/Objective C/Java/C#, ...), then transmit it to optimised byte code with LLVM, and finally to asm.js with Emscripten.
Where is a gain? LLVM is a project since 2000 that does excellent job in the optimisation of statically-typed languages into a low-level byte code. For example we can get C++ code, transfer it to the mentioned pipeline and at the end get Java-Script code in a kind of optimised assembler style.
Of course there are limitations and you cannot call special OS functions in an optimised way. Currently only value-type manipulations (integer, float, etc) with standard Math library are supported, external function calls and heap access.

As a hint to an engine about optimised function there be a "use asm;" line, the hint itself is a prologue directive.

function Module(stdlib, foreign, heap) {
    "use asm";
    // module body
function NativelyFastCalculation(habraHugs)
   return stdlib.Math.sqrt(habraHugs); 
    return { module: module };

Then we can call our optimised function from any part of a usual non-optimised Java-Script code.

One of the areas with enormous structure manipulations is 3d calculation. Epic games and Mozilla converted 1 million lines of Unreal engine to Java-Script with asm.js and were able to get good performance:

Bananabread (demo) is another example of conversion Cube 2 engine, written in C++ and OpenGL, to Java-Script.

Current asm.js has draft version and is a subset of ECMAScript 6. So only browser supporting ES6 has full support of asm.js. In general vendors started experimenting with the subset a while ago. Mozilla was the first with Firefox 22, Chrome added special support in version 28, and recently Microsoft lined up with Chakra/Spartan. Within each version vendors provide better optimisation, e.g. usage of ahead-of-time compilation.

Firefox presented asm.js with

  • Cross platform
    Already supported by all modern browsers, which is rare in the history. Architecture independent (ARM, x86, x64).
  • Performance
    The data differs from vendor to vendor and the reports show 75% to 10% of native client performance.
  • Partial backward compatibility
    If you do not use new features from EcmaScript6 (e.g. Typed arrays) then old browsers automatically support asm.js 
  • Minimised (non readable) code
    Users care about speed and do not care about page source code. Dear readers with a doubt, just view the source in Google and Facebook site.
    Now debugging is a problem, but can be solved in future with debugger symbol mapping.
  • Conversion from other languages through LLVM (C/C++/Java/C#/...)
  • Limited types
    Now only value types and operations on typed arrays. And you cannot manipulate DOM. However there are plans for extension. 
At present project has a very good start, the future will show us result.

It is worth to mention Low Level Java-Script project, which seems ideal for integration into asm.js, and possibly Mozilla team will do it.

In further parts we will see Google idea with Dart project, and then new web byte code library by popular browser vendors.

No comments:

Post a Comment