Webassembly

WebAssembly (Wasm) is a binary instruction format for stack-based virtual machines, a low-level assembly language designed to be very close to compiled machine code and very close to native performance. This article will introduce its advantages and usage scenarios, and experience the process of WebAssembly project development through code.

Simply put, Wasm is a compilation target that allows code written in about 30 languages to be compiled into .wasm files using WebAssembly-specific tools. collector). Support for the Go, Python, and JavaScript ecosystems is also growing rapidly. The .wasm file generated by compilation can be in the browser or on the server. The .wasm file contains binary instructions that can be read by virtual machines, and because Wasm targets virtual machines, it is suitable for many chip architectures that target the lowest common denominator of popular hardware, the stacker, which is what sets it apart from other targets for generating binary code.

Wasm was originally built for the browser, but as the technology has matured, it is seeing more and more use cases on the server side. In this article, we again introduce the advantages and application scenarios of WebAssembly and get acquainted with its project development process through examples, by clicking View Code.

What advantages does it have

Wasm allows to write code in a familiar language and run it from anywhere.

Faster startup times

On the server, Wasm can achieve cold start times 10-100 times faster than Docker containers because it doesn’t need to create an OS process for each container. In the browser, decoding Wasm is faster than parsing, interpreting and optimizing JavaScript, so Wasm code executes faster in the browser than JavaScript.

Near-Native Performance

There is some debate about the performance details of Wasm, but it has the advantage of allowing users to encapsulate the computationally intensive parts of their applications into a lower-level language. Many of Wasm’s performance benefits come from the fact that it (it is Wasm code) is built to be as close to native machine code as possible.

Lightweight

The Wasm binaries are small, so they use only a small amount of bandwidth and typically take less time to transfer over the network than cross-compiled JavaScript in the browser.

Convenience and versatility

Any Wasm runtime can run any Wasm code (although not all runtimes support all Wasm extensions, i.e. different WASI interface types). Most browsers support WebAssembly, and there are many server-side runtimes (WasmEdge, Wasmtime, etc.) that run Wasm code. Given the extensive browser and server (and hardware) support for Wasm, it is portable and also very general, with about 30 languages that can be compiled or executed in it (C, C++, Rust, Python, Go, AssemblyScript, JavaScript, etc.).

Security

The two goals of the WebAssembly security model are.

  1. To protect users from bugs and or malicious modules.
  2. Provide developers with the original language needed to develop secure applications. To this extent, the scope of Wasm is limited, and the code running in the Wasm runtime is memory sandboxed and functionally restricted.

The above points make it interesting for both client and server applications. On the client side, there is a world where (thanks in part) to Wasm, the browser ends up being the default operating system on which all applications run. On the server, Wasm is likely to become the next default container system. what Docker does for virtual machines, Wasm will do for Docker. As Matt Butcher of Fermyon said.

If VMs are the heavyweight of cloud computing and containers are the mid-level, then WebAssembly is the perfect choice for the lightweight.

Application Scenarios

Wasm will provide fast and secure client and server applications, what are the application scenarios?

Accelerated WEB applications

According to the Figma use case, with Wasm, it is possible to write the performance/computation-intensive part of the application in JavaScript and then replace the JavaScript with a higher performance language, such as Rust/C/C++. But this is not always the case.

Everything is a (web) application

Write once, run everywhere, WebAssembly hopes to fulfill this dream of a Java-related term originally coined by Sun Microsystems. This is not an easy feat in practice, but Wasm definitely makes it easier to bring applications to the previously native Web (and other platforms). Photoshop and Autodesk Web are good examples.

Plugin

Wasm is well suited for executing untrusted code in an isolated sandbox. Once most platforms scale, eventually a plug-in system is built that allows end users to build custom software that interacts with their platform. By using Wasm in this plug-in system, platforms can let their users build plug-ins in any language without worrying about the security risks of letting them execute untrusted code, since that code is sandboxed. All the other benefits of Wasm come into play here as well: speed, small binaries, and fast loading. By default, every plugin system wants high performance, security, and ease of use, and Wasm helps achieve that goal.

New Container System

As mentioned above, Wasm has a constrained security model, it is cross-OS, has a fast cold start time, has excellent performance, does not require creating a new OS process for each container, and takes up very little space. These are all attractive features of a new container system that could replace Docker. As Solomon Hykes tweeted, WASI is the missing link that really drives this new container system forward.

Package Manager

WebAssembly will have a package registry and manager. WAPM was the first to try this, and once the WASI and component models are ubiquitous, there will be many compelling reasons why the Wasm package manager should be used.

Games

In the browser, WebAssembly can be great for reasons related to its usefulness for performance-intensive Web applications: to make them run efficiently on the Web. According to the WebAssembly documentation, examples include lightweight games that need to start quickly, asset-intensive AAA games, and peer-to-peer games. Also according to the WebAssembly documentation, it can be used on the server to create game distribution services that make games portable and secure.

blockchain

There has been a lot of talk about Wasm as an alternative to EVM, and the Parity Ethereum Client runs Wasm bytecode in Wasmi, which allows Wasm code to access and interact with the blockchain. Another good example is ewasm, which is currently being worked on as an alternative to EVM1 (source). It is designed to allow developers to use WebAssembly to interact with the ethereum blockchain, thus supporting more languages.

untrusted code server-side computing

A similar use case to the plug-in system is untrusted code server-side computing. Many platforms eventually expose their systems to allow end users to write code on their platforms, such as Airtable Scripts. using Wasm, platforms like Airtable allow their users to write functions in multiple languages on the Airtable Scripting platform.

Serverless Computing

Serverless functions are the perfect scenario for WebAssembly, and Wasm’s sandboxing, performance, fast startup time, and language support make it the perfect technology for running serverless functions.

Machine Learning

As IoT / connected devices that work in real-time become more popular, being able to perform real-time machine learning will become critical. Runtimes like WasmEdge make this possible.

Hello World

In this article, we will use AssemblyScript to build “Hello World” by creating the project directory wasm-hello and executing the following command.

1
npm init

After the initialization is complete, execute the following command.

1
npm install --save-dev assemblyscript

After installation, the compiler provides a handy scaffolding utility to quickly set up a new project by executing the following command in the current directory.

1
npx asinit .

The asinit command automatically creates the recommended directory structure and configuration files.

  • . /assembly: directory where AssemblyScript sources compiled to WebAssembly are stored.
  • . /assembly/tsconfig.json : The TypeScript configuration inherits the recommended AssemblyScript settings.
  • . /assembly/index.ts : The project entry file
  • . /builds : The build artifacts directory where compiled WebAssembly files are stored.
  • . /build/.gitignore.
  • . /asconfig.json.
  • . /package.json
  • . /tests/index.js
  • . /index.html

Next, create a scripts to hold the JavaScript code files and create the file main.js, a function that loads the Wasm module using the WebAssembly Web API.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const wasmBrowserInstantiate = async (wasmModuleUrl, importObject) => {
    let response = undefined;

    if (!importObject) {
        importObject = {
            env: {
                abort: () => console.log("Abort!"),
            },
        };
    }

    // Check if the browser supports stream instantiation
    if (WebAssembly.instantiateStreaming) {
        // Get the module and instantiate it on download
        response = await WebAssembly.instantiateStreaming(
            fetch(wasmModuleUrl),
            importObject
        );
    } else {
        const fetchAndInstantiateTask = async () => {
            const wasmArrayBuffer = await fetch(wasmModuleUrl).then(
                (response) => response.arrayBuffer()
            );
            return WebAssembly.instantiate(wasmArrayBuffer, importObject);
        };
        response = await fetchAndInstantiateTask();
    }

    return response;
};

Next, instantiate the wasm module by loading it with the above function, and call the exported add() function from the Wasm module.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
const runWasm = async () => {
    // Instantiating the wasm module
    const wasmModule = await wasmBrowserInstantiate("./build/core.wasm");

    // Calling the add function from wasm
    const addResult = wasmModule.instance.exports.add(24, 24);

    // Adding function execution results to the DOM
    document.getElementById(
        "result"
    ).innerHTML = `Hello World! addResult: ${addResult}`;
};
runWasm();

Go back to the html file in the project directory and code it as follows.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8" />
        <title>Hello World - AssemblyScript</title>

    </head>

    <body>
        <div id="result">

        </div>
        <script src="./scripts/main.js"> </script>
    </body>

</html>

Start the app.

1
npm start

You can see the effect, note that the latest version to upgrade the node environment to version 16 or more. The code on github is a more complex example (from the official source), which runs as follows.

wasm-study