What is WebAssembly

WebAssembly is a fast, secure, and portable low-level code format designed for efficient execution and compact presentation to run on modern processors, including browsers, with a compact binary format that can run with near-native performance. The WebAssembly Core specification was announced as an official standard by the W3C on 5 December 2019. The name indicates assembly language for the Web. Instead of directly using assembly language, however, WebAssembly provides a transformation mechanism (LLVM IR) that compiles high-level languages (AssemblyScript, Go, C, C++, Rust, etc.) into WebAssembly, giving you the opportunity to perform low-level binary syntax through a Web browser.

The characteristics of WebAssembl

WebAssembly is a different language from JavaScript, it is not designed to replace JavaScript. Instead, it is designed to work with JavaScript so that web developers can take advantage of both languages by using WebAssembly’s JavaScriptAPI, You can load WebAssembly modules into a JavaScript application and share functionality between the two. This allows you to take advantage of The performance of WebAssembly and the expressive power and flexibility of JavaScript in the same application, even though you may not know how to write WebAssembly code.

  • Fast: Dramatically improves Javascript performance to approximate native code performance.
  • Secure: Code is validated and executed in a memory-safe sandbox environment to prevent data corruption or security breaches.
  • Language-independent: Allows any language to compile to WebAssembly, and you can write web pages in other high-level languages.
  • Hardware-agnostic: It can be compiled on all modern architectures, desktop or mobile devices, and embedded systems.
  • Platform-independent: It can be embedded in a browser, run as a standalone VM, or integrated into other environments.
  • Compact: A binary format with faster transmission speeds than typical text or native code formats.
  • Modularity: Programs can be divided into smaller parts that can be transferred, cached, and used separately.
  • Efficient: Can be decoded, validated, and compiled with a quick pass, equivalent to just-in-time (JIT) or AOT compilation.
  • Streamable: Allows decoding, validation, and compilation to begin as soon as possible before all data is seen.

Why is WebAssembly more efficient than JavaScript

One of the most attractive features of WebAssembly is its execution efficiency, which is much more efficient than JavaScript for the following reasons:

  • File fetching phase: WebAssembly is faster than JavaScript fetching files. WebAssembly files are smaller than JavaScript even when JavaScript is compressed;
  • Parsing phase: WebAssembly’s decoding time is shorter than JavaScript’s parsing time;
  • Compilation and optimization phase: WebAssembly has an advantage because WebAssembly code is closer to machine code, whereas JavaScript code is optimized through the server side first.
  • Retuning phase: WebAssembly does not retune. However, the optimization hypothesis of JS engine may occur the phenomenon of “discarding optimized code <-> re-optimization”.
  • Execution phase: WebAssembly is faster because developers don’t need to know as much about compiler skills as they do in JavaScript. WebAssembly code is also better suited to generating instructions that the machine can execute more efficiently.
  • Garbage Collection phase: WebAssembly garbage collection is manually controlled and more efficient than automatic collection.

How do I use WebAssembly

The high-level language is compiled to the.wasm file

WebAssembly bytecode is a type of machine code that is flattened out across different CPU architectures. WebAssembly bytecode cannot run directly on any CPU architecture, but can be translated into the corresponding machine code very quickly because it is so close to the machine code. So WebAssembly runs at close to machine code speed, which sounds a lot like Java bytecode. To compile to WebAssembly, you need to compile LLVM first. See WebAssembly.org. LLVM

  • LLVM IR to different CPU architecture machine code generation;
  • Machine code compile-time performance and size optimization.

LLVM implements LLVM IR to WebAssembly bytecode compilation, that is, as long as the high-level language can be converted to LLVM IR, it can be compiled into WebAssembly bytecode. Currently, compilation to WebAssembly mainly includes C, C++, Rust, Go, AssemblyScript (similar to TypeScript), etc.

AssemblyScript is the easiest way to use the front end. AssemblyScript is slightly different from TypeScript, and uses TypeScript to compile to WebAssembly with more stringent type restrictions. AssemblyScript uses LLVM to parse TS source code into AST through TypeScript compiler, translate AST into IR, and compile WebAssembly bytecode through LLVM. Integration with existing Web ecosystems – no heavy toolchains to set up. Just install it by NPM and compile AssemblyScript into WebAssembly via ASC.

Refer to AssemblyScript for installation

NPM init NPM install --save-dev assemblyscript/loader NPM install --save-dev Assemblyscript // Create the recommended directory structure and configuration file NPX asinit.Copy the code

The original Assemblyscript, which derives a function to get the NTH prime number

/** * if a number is prime * @param x */
function isPrime(x: u32) :bool {
  if (x < 2) {
    return false;
  }

  for (let i: u32 = 2; i < x; i++) {
    if (x % i === 0) {
      return false; }}return true;
}

/** * get the NTH prime * @param x */
export function getPrime(x: u32) :number {
  let index: u32 = 0;

  let i: u32 = 2;
  do {
    if (isPrime(i)) {
      ++index;
    }
    ++i;
  } while(index ! == x);return i - 1;
}
Copy the code

Corresponding JS code

/** * if a number is prime * @param x */
function isPrime(x) {
    if (x < 2) {
        return false;
    }
    for (let i = 2; i < x; i++) {
        if (x % i === 0) {
            return false; }}return true;
}


/** * get the NTH prime * @param x */
function getPrime(x) {
    let index = 0;
    let i = 2;
    do {
        if (isPrime(i)) {
            ++index;
        }
        ++i;
        env.console.log('hello')}while(index ! == x);return i - 1;
}
Copy the code

Compiled into WebAssembly

asc assembly/index.ts -b build/optimized.wasm
Copy the code

Load the WASM module into JavaScript in the browser

In future plans, WebAssembly modules can be loaded using ES6 modules (using

Once the WebAssembly instance is obtained, it can be invoked through JS. The browser provides the WebAssemblyAPI to compile WebAssembly

  • WebAssembly.com compile() compiles the WebAssembly binary
  • WebAssembly.com pileStreaming () from the original bytecode compilation WebAssembly binary code
  • Webassembly.instantiate () allows you to compile and instantiate WebAssembly code
  • WebAssembly. InstantiateStreaming () directly from streaming the underlying source compilation and instantiate WebAssembly module. This is a very efficient optimization for loading WASM code

Compile in the browser to get the WebAssembly instance

(async() = > {// Contains some objects that you want to import into the newly created Instance value, importing the external API for internal calls
    const importObject = {
        env: {
            abort(_msg, _file, line, column) {
                console.error("abort called at index.ts:" + line + ":" + column);
            },
            console: console}};const module = await WebAssembly.instantiateStreaming(
        fetch("./build/optimized.wasm"),
        importObject
    );
    
    // Get the exported module
    module.instance.export.getPrime
})();
Copy the code

The horizontal axis is the NTH prime number, and the vertical axis is the calculation time (ms). It can be seen from the results that the sales volume of WebAssembly is significantly higher than that of JS.

Efficiency comparison is not fixed, different functions, different functions will be different

More than just browsers

As a kind of low-level bytecode, WebAssembly can run in other environments besides browsers

Execute the WASM binary directly

Brew Install Binaryen on a Mac operating system. After Binaryen is successfully installed on a Mac operating system, you can run it directly from the wASM -shell f. asm file

The WASM module is loaded in the node

WebAssembly support has been added to V8 JS engine. When V8 JS engine runs WebAssembly, WebAssembly and JS are executed in the same VIRTUAL machine, instead of WebAssembly running in a separate virtual machine. This makes it easier for JS and WebAssembly to call each other. Running WebAssembly in a Nodejs environment makes little sense because Nodejs supports running native modules, which perform better than WebAssembly. If you are writing WebAssembly through C and Rust, you can compile directly into native modules that Nodejs can call.

const fs = require("fs");
const loader = require("@assemblyscript/loader");
module.exports = loader.instantiateSync(fs.readFileSync(__dirname + "/build/optimized.wasm"), { /* imports */ })
Copy the code

WebAssembly was designed in part to address JavaScript performance issues and bring Web applications close to the performance of native applications. As a general purpose, open and efficient abstraction of the underlying VIRTUAL machine, many programming languages (such as C/C++,Rust, etc.) can compile existing applications into WASM object code to run in the browser. This decouples application development techniques from runtime techniques, greatly facilitating code reuse.

And finally, a tweet from Docker founder Solomon Hykes at WASI’s launch