In my previous blog post, I presented an example of universal code and outlined some guidelines on how to best approach writing code that can be deployed on every target without modification. I am going to continue posting examples and interesting pieces of code that you can freely copy and experiment with, but before we continue I want to take a moment to talk about WebAssembly.
Those that have followed me on Facebook or perhaps read my personal blog over the years, know that JavaScript has occupied more than a decade of my professional life. I have held presentations on JavaScript, blogged about JavaScript and thrown the occasional tantrum, lamenting over its inherently flawed nature.
Alas, despite my best efforts at ignoring web technology in the past, JavaScript turned out to be a universal constant - something you just have to deal with whether you like it or not. And as my idealism cooled down, I found myself strangely attracted and at home with web technology.
Fast forward to today, and I find myself just as enamored with WebAssembly as I was with JavaScript, this time thanx to RemObjects' Elements compiler.
WebAssembly is not JavaScript
Before we dig into web technology as a strategy, let's have a quick look at the evolution of JavaScript and and the browser so far. Because for the past 10 years, no other technology on the planet has received as much attention as the browser. Not even the Linux subsystem, which is infinitely more valuable, can compete with the onslaught of development geared at making web technology a reality.
As of writing, coding for the browser has seen three stages of evolution:
- Ordinary JavaScript
- Asm.js
- WebAssembly
Ordinary JavaScript
JavaScript has not stood still over the past decade. It has evolved from a somewhat amusing but irritating toy in the early 2k's into a powerful development system capable of great things. I say development-system rather than language, because JavaScript as a language has evolved very little; most of the effort has gone into strengthening its infrastructure and executing code faster.
It's important to draw the distinction between the language and and its environment (the JavaScript virtual machine). The JavaScript of the 90's and early 2k's was solely interpreted. Google introduced proper JIT compilation with their Chrome browser. What made Chrome special is that behind the scenes, JavaScript is parsed, tokenized and converted into bytecodes. Depending on the complexity of said bytecodes, it's either JIT-compiled into machine-code or executed instruction by instruction. The latter being leaps and bounds faster than blunt interpretation.
Asm.js
When Google started compiling JavaScript into bytecodes behind the scenes, it was only a matter of time before the same idea would be applied elsewhere. And one of these experimental technologies is what we know as Asm.js.
Asm.js is a technique (just to make that clear). It demands no alteration of the browser, like WebAssembly does, nor does it rely on plugins like Adobe Flash operated with. In short, it was discovered that JavaScript could execute at high speeds, providing it dealt with buffer operations. Modern virtual machines like Google's V8 and Mozilla's Spidermonkey have optimized memory manipulation to ludicrous levels; the same is true for a subset of JavaScript's functions (or operators to be accurate).
To take advantage of this, a group of enthusiasts modified the Gnu C/C++ compiler to emit bytecodes rather than machine-code, and these bytecodes were then loaded into a memory buffer. A tiny execution engine written in JavaScript, with heavy emphasis on these speedy instructions, would then execute the bytecodes as quickly as possible.
Perhaps you have seen games like Quake III run at full speed directly in the browser? Those demos are indeed Asm.js, so the power of this technique should not be dismissed.
But Asm.js, despite being capable of amazing things, is ultimately a product of vanilla JavaScript. These bytecodes are only as fast as the code reading and executing them. Which means that Asm.js can never be faster than JavaScript itself.
Note: I want to stress that Asm.js is by no means a defunct standard. Asm.js remains a labor of love by a handful of passionate web developers, and like I underlined - it's a technique rather than something you would find an RFC for. Anyone can emit their own bytecodes into a buffer and execute it. There is no right or wrong way here, except what works and what doesn't.
WebAssembly
One of the things developers learned from Asm.js experiments was that the core developers behind Chrome and Firefox had to get on board. Sure, Asm.js is very capable, but without a proper standard adopted by both Google, Microsoft, Apple and the Mozilla foundation, the quality and safety of such code could never be guaranteed.
WebAssembly has an intermediate format called WAST. It might look indecipherable, but thankfully you don't have to deal with it unless you want to.
Secondly, far better performance could be gained by moving the execution of said bytecodes out of JavaScript JIT space - and into the actual browser itself. Obviously natively compiled C code can chew bytecodes much faster than any snippet of JavaScript.
And this is, for all means and purposes, how WebAssembly was born.
Benefits of WebAssembly
The immediate benefit of WebAssembly is obviously speed. WebAssembly is not JavaScript, it's not bound by JavaScript nor subject to its laws in any way. JavaScript is still used to load and initiate the execution of WebAssembly binaries, but that's because JavaScript is the de-facto language of the browser.
With this speed you can finally develop software vanilla JavaScript is incapable of; on the top of my head I can think of the following:
- Sophisticated business applications
- Compression
- Encryption
- Photoshop level image manipulation
- Final cut style video engineering
- Pro-tools quality audio processing
- Natural language analysis
- 3D modeling and ray-tracing
- Machine learning and A.I
.. and much more
There is also another benefit (depending on how you see it), and that is synchronous execution. WebAssembly was not designed to be another JavaScript. There is no "WebAssembly, the language" involved here. WebAssembly is a low-level specification designed for compiler vendors. It has nothing in common with general purpose programming. The idea is that WASM is emitted by a dedicated toolchain.
I mean, JavaScript is wholeheartedly asynchronous by nature – cooperative multitasking if you will – where even construction of object prototypes is done on idle cycles. WebAssembly is synchronous, linear, top-down, blocking execution all the way. And it was designed as such because the whole purpose of WebAssembly is to be a target for traditional programming languages.
I have briefly mentioned C/C++ as used by the Asm.js initiative; not surprisingly that is also true for WebAssembly. So different language vendors are slowly coming to terms with WebAssembly as a target, with radically different approaches on how to best leverage the technology. Some chose to do a clean break with HTML and DOM (document object model) completely, and implement their own graphics libraries etc. that do everything on their own, others are going for a more HTML friendly approach.
As of writing, Elements represents the only WebAssembly offering that spans five languages (Oxygene, C#, Swift, Java and Go). The way we have organized our tool chain means that you can go down both paths, the HTML friendly path, and the solo path. There is nothing stopping you from doing your own thing separate from the browser. Or, you can opt for a more moderate approach and enjoy the best of both worlds.
This is perhaps a good time to mention our Delphi VCL compatibility library. This is a clone of the much loved VCL framework that Delphi users love so much. And it's designed to make porting code from Delphi easier. This library can be used by all our languages, so even though you are coding in Swift or Go, you can tap into our VCL to become productive faster. And it is supported from WebAssembly to craft HTML user interfaces.
Work Strategy
If you have a large and evolved codebase rooted in JavaScript, you might be wondering how exactly you are going to benefit from WebAssembly? Do you have to re-write your entire front-end to reap these benefits?
Thankfully that is not the case. You can start benefiting from WebAssembly almost immediately providing you know one of the five high-level languages we deliver.
WebAssembly can be used in one of two ways:
- To write full applications
- To create libraries
If you are presently heavily invested in JavaScript, be it for your front-end (read: your website or web app) or a node.js back-end, you might want to start by gradually empowering your existing codebase.
You can implement the code that does all the heavy lifting in WebAssembly, and simply call these methods instead of your older JavaScript functions. This is something you can do right now and reap instant rewards.
If you are starting a new application, you can mix and match between both worlds. I would design the UI as normal HTML, perhaps find a cool library like JQuery UI or Sencha Ext JS and make a polished, animated and interactive user interface. And once that is in place, you can easily reference the buttons, lists, text boxes etc. directly from WebAssembly.
Conclusions
I hope this brief overview of WebAssembly has been informative. We have only scratched the surface of what WebAssembly can do, and I will return to this topic in the near future.
For me at least, WebAssembly is a much needed technology, one I have been hoping for since the NetScape Navigator days. JavaScript is cool, but there are some things that require the weight of a traditional toolchain.
As a target that all our languages can use, WebAssembly is here to stay.