AssemblyScript Getting Started Guide

Author: Danny Guo

Translate: Crazy Technology House

Original: https://blog.logrocket.com/th...

Reproduction is strictly prohibited without permission

WebAssembly (Wasm) is a relatively new feature in Web browsers, but it expands the functional potential of using the Web as a service application platform.

Learning to use Web Assembly can be a difficult process for Web developers, but AssemblyScript Provides a solution.Let's first look at why Web Assembly is a promising technology, then how AssemblyScript can tap into its potential.

WebAssembly

Web Assembly is the low-level language of browsers and provides developers with Web compilation targets in addition to JavaScript.It allows site code to run at near native speed in a secure sandbox environment.

It was developed based on the opinions of all major browsers (Chrome, Firefox, Safari and Edge), and they Design consensus reached These browsers now support WebAssembly.

Web Assembly is delivered in binary format, which means that it has advantages in size and load time compared to JavaScript.But it's also easy to understand Text representation.

When Web Assembly was first published, some developers thought it might eventually replace JavaScript as the primary language for the Web.But it's best to think of Web Assembly as a new tool that integrates well with existing Web platforms, which is Advanced Goals.

Instead of replacing existing use cases for JavaScript, Web Assembly attracts more people because it introduces new use cases.Web Assembly currently does not have direct access to the DOM, and most websites want to use JavaScript, which has been optimized for many years and is fairly fast.The following WebAssembly List of possible use cases Example:

  • Game
  • Scientific visualization and simulation
  • CAD Application
  • Image/Video Editing

The common feature of these applications is that they are often considered desktop applications.By providing near native performance for CPU-intensive tasks, Web Assembly makes it possible to migrate these programs to the Web.

Existing websites can also benefit from Web Assembly.Figma( https://www.figma.com/) A real-world example is provided, which greatly reduces its load time by using Web Assembly.If your site uses code that does a lot of calculations, you can replace it with Web Assembly to improve performance.

Perhaps now you're interested in how to use Web Assembly.You can learn the language itself and Direct Writing But it actually intends to become Compilation target for other languages .It is Design Good support for C and C++, GoLanguage Adding experimental support in version 1.11 In the version of Significant investment has been made.

But perhaps you don't want to learn or use one of these languages in order to use Web Assembly.This is what AssemblyScript means.

AssemblyScript

AssemblyScript is a compiler that converts TypeScript to Web Assembly.TypeScript, developed by Microsoft, adds types to JavaScript.It has become Quite popular AssemblyScript only allows a limited subset of TypeScript functionality, even for people unfamiliar with it, so it doesn't take much time to get started.

Because it is very similar to JavaScript, AssemblyScript makes it easy for Web developers to integrate Web Assembly into their Web sites without having to use a completely different language.

On trial

Let's write the first AssemblyScript module (all of the following are available in On GitHub Find).We need Node.js Minimum version 8 is available Support for Web Assembly.

Go to an empty directory, create a package.json file, and install AssemblyScript.Please note that we need to go directly from Its GitHub repository Install.It has not been published on npm because of the AssemblyScript developer Whether the compiler is ready has not been considered Can support widespread use.

mkdir assemblyscript-demo
cd assemblyscript-demo
npm init
npm install --save-dev github:AssemblyScript/assemblyscript

Use the asinit command to generate scaffolding files:

npx asinit .

Our package.json should now contain the following scripts:

{
  "scripts": {
    "asbuild:untouched": "asc assembly/index.ts -b build/untouched.wasm -t build/untouched.wat --sourceMap --validate --debug",
    "asbuild:optimized": "asc assembly/index.ts -b build/optimized.wasm -t build/optimized.wat --sourceMap --validate --optimize",
    "asbuild": "npm run asbuild:untouched && npm run asbuild:optimized"
  }
}

The top index.js looks like this:

const fs = require("fs");
const compiled = new WebAssembly.Module(fs.readFileSync(__dirname + "/build/optimized.wasm"));
const imports = {
  env: {
    abort(_msg, _file, line, column) {
       console.error("abort called at index.ts:" + line + ":" + column);
    }
  }
};
Object.defineProperty(module, "exports", {
  get: () => new WebAssembly.Instance(compiled, imports).exports
});

It enables us to require the Web Assembly module as easily as using normal JavaScript modules.

The assembly directory contains our AssemblyScript source code.The resulting example is a simple addition function.

export function add(a: i32, b: i32): i32 {
  return a + b;
}

Function signatures are just like they are in TypeScript, and the reason they use i32 is because AssemblyScript uses Web Assembly's Specific integer and floating point types Rather than TypeScript's Universal number Type.

Let's build an example.

npm run asbuild

The build directory should now contain the following files:

optimized.wasm
optimized.wasm.map
optimized.wat
untouched.wasm
untouched.wasm.map
untouched.wat

We have both the normal and optimized versions of the build.For each build version, there is a.wasm binary file, and a.wasm.map Source Mapping And the.wat text representation of the binary file.Text representations are meant to be read, but now we don't need to read or understand them -- one of the purposes of using AssemblyScript is that we don't need to use the original WebAssembly.

Start Node and use the compiled module like any other module.

$ node
Welcome to Node.js v12.10.0.
Type ".help" for more information.
> const add = require('./index').add;
undefined
> add(3, 5)
8

That's all you need to call WebAssembly from Node!

Add monitoring scripts

For ease of development, I recommend that you use this every time you change the source code onchange Automatically rebuild module because AssemblyScript Monitoring mode is not included yet.

npm install --save-dev onchange

Add an asbuild:watch script to the package.json.Contains-i flag That runs the initial build immediately after running the command.

{
  "scripts": {
    "asbuild:untouched": "asc assembly/index.ts -b build/untouched.wasm -t build/untouched.wat --sourceMap --validate --debug",
    "asbuild:optimized": "asc assembly/index.ts -b build/optimized.wasm -t build/optimized.wat --sourceMap --validate --optimize",
    "asbuild": "npm run asbuild:untouched && npm run asbuild:optimized",
    "asbuild:watch": "onchange -i 'assembly/**/*' -- npm run asbuild"
  }
}

Now you can run asbuild:watch without having to constantly rerun asbuild.

performance

Let's write a basic benchmark to see what performance improvements we can achieve.WebAssembly's expertise is in CPU-intensive tasks such as digital computing, so we use a function to determine if integers are prime.

Our reference implementation is shown below.This is a naive solution to violence because our goal is to do a lot of computing.

function isPrime(x) {
    if (x < 2) {
        return false;
    }

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

    return true;
}

Equivalent versions of AssemblyScript require only a few type comments:

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;
}

We will use Benchmark.js.

npm install --save-dev benchmark

Create benchmark.js:

const Benchmark = require('benchmark');

const assemblyScriptIsPrime = require('./index').isPrime;

function isPrime(x) {
    for (let i = 2; i < x; i++) {
        if (x % i === 0) {
            return false;
        }
    }

    return true;
}

const suite = new Benchmark.Suite;
const startNumber = 2;
const stopNumber = 10000;

suite.add('AssemblyScript isPrime', function () {
    for (let i = startNumber; i < stopNumber; i++) {
        assemblyScriptIsPrime(i);
    }
}).add('JavaScript isPrime', function () {
    for (let i = startNumber; i < stopNumber; i++) {
        isPrime(i);
    }
}).on('cycle', function (event) {
    console.log(String(event.target));
}).on('complete', function () {
    const fastest = this.filter('fastest');
    const slowest = this.filter('slowest');
    const difference = (fastest.map('hz') - slowest.map('hz')) / slowest.map('hz') * 100;
    console.log(`${fastest.map('name')} is ~${difference.toFixed(1)}% faster.`);
}).run();

On my machine, running node benchmark yields the following results:

AssemblyScript isPrime x 74.00 ops/sec ±0.43% (76 runs sampled)
JavaScript isPrime x 61.56 ops/sec ±0.30% (64 runs sampled)
AssemblyScript isPrime is ~20.2% faster.

Note that this test is a microbenchmark We should read with caution.

For some more AssemblyScript benchmarks, I recommend you review WasmBoy Benchmark and Benchmark test of wave equation.

Loading modules

Next, use our modules in the website.

Create index.html first:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>AssemblyScript isPrime demo</title>
    </head>
    <body>
        <form id="prime-checker">
            <label for="number">Enter a number to check if it is prime:</label>
            <input name="number" type="number" />
            <button type="submit">Submit</button>
        </form>

        <p id="result"></p>

        <script src="demo.js"></script>
    </body>
</html>

Create demo.js again.Loading the Web Assembly module is Multiple ways However, the most effective method is to compile and instantiate streams using the WebAssembly.instantiateStreaming function.Note that if assertion If it fails, we need Provide abort function.

(async () => {
    const importObject = {
        env: {
            abort(_msg, _file, line, column) {
                console.error("abort called at index.ts:" + line + ":" + column);
            }
        }
    };
    const module = await WebAssembly.instantiateStreaming(
        fetch("build/optimized.wasm"),
        importObject
    );
    const isPrime = module.instance.exports.isPrime;

    const result = document.querySelector("#result");
    document.querySelector("#prime-checker").addEventListener("submit", event => {
        event.preventDefault();
        result.innerText = "";
        const number = event.target.elements.number.value;
        result.innerText = `${number} is ${isPrime(number) ? '' : 'not '}prime.`;
    });
})();

Install now static-server .Because to use WebAssembly.instantiateStreaming, we need to create a service that uses MIME type application/wasm of.

npm install --save-dev static-server

Add the script to package.json.

{
  "scripts": {
    "serve-demo": "static-server"
  }
}

Run npm run serve-demo and open the localhost URL in the browser.Submit the number in the form and you will receive a message indicating whether it is a prime number.Now we've implemented the entire process from coding with AssemblyScript to actually using it on the Web site.

conclusion

Web Assembly and its expansion through AssemblyScript don't magically make every website faster, but it doesn't matter.Web Assembly is exciting because it makes more applications possible on the Web.

Similarly, AssemblyScript enables more developers to use WebAssembly, which makes it easy to default to JavaScript, but when a lot of computational work is required, WebAssembly can be used.

WeChat Public Number for the First Issue of this Article: A Pioneer

Welcome to Scan QR Code for Public Numbers and push you fresh front-end technical articles every day

Welcome to continue reading other great articles in this column:

Keywords: Javascript npm TypeScript JSON

Added by Avalanche on Wed, 20 Nov 2019 07:19:44 +0200