AssemblyScriptを使ってTypeScriptをWebAssemblyにコンパイルする

今回は、AssemblyScript を使って TypeScript(.ts)を WebAssembly(.wasm)にコンパイルし、それを Node.js で実行するやり方について紹介します。

最初に結論を言っておきます。Gaussの消去法で連立一次方程式を解くプログラムを使って、C から生成した WebAssembly と TypeScript から生成した WebAssembly の処理時間を比較したところ、TypeScript の方が C に比べ約40倍、処理時間がかかりました。ということで、配列を操作するようなプログラムの場合は、迷わず C から WebAssembly にコンパイルしてください。

注)C(.c)を WebAssembly(.wasm)にコンパイルするには、EmscriptenWebAssembly Studio を使います。AssemblyScript ではできません。

AssemblyScript のインストールは、Node.js がインストールされていれば、npm を使って下記のようにコマンドを入力するだけで簡単にインストールできます。

〈ローカルインストール〉

> cd /d D:\assemblyscript
> npm install assemblyscript

 

コンパイルと実行〉

> cd /d D:\assemblyscript
> set path=node_modules\.bin;%path%;
> asc -O3 module.ts -o module.wasm
> node main.js

 

〈ファイルの配置〉

D:\assemblyscript\main.js
D:\assemblyscript\module.ts
D:\assemblyscript\module.wasm

 

main.js

const imports = {env:{abort:(message, file, line, column) => console.error(`Abort at (${line}, ${column})`)}};
const instance = new WebAssembly.Instance(new WebAssembly.Module(require("fs").readFileSync("module.wasm")), imports);
console.log(instance.exports.add(1, 2));
 

 

module.ts

export function add(x:f64, y:f64):f64 { return x + y; }
 

次は、Gaussの消去法で連立一次方程式を解くプログラムです。

main.js

const imports = {env:{abort:(message, file, line, column) => console.error(`Abort at (${line}, ${column})`)}};
const instance = new WebAssembly.Instance(new WebAssembly.Module(require("fs").readFileSync("gauss.wasm")), imports);
for (let i = 0; i < instance.exports.length(); i++) console.log(instance.exports.getb(i));
 

 

gauss.ts

let a = [[1.2, 0.5, 9.2, 7.6, 2.1], [9.8, 1.3, 8.4, 5.3, 3.3], [4.1, 2.7, 1.4, 7.3, 5.6], [0.2, 8.7, 4.5, 1.9, 0.6], [3.7, 6.4, 5.6, 2.6, 1.7]];
let b = [1.9, 8.3, 5.1, 3.4, 7.2];
solve(a, b);
export function length():f64 { return a.length; }
export function getb(i:i32):f64 { return b[i]; }
function solve(a:f64[][], b:f64[]):void {
  const length = a.length;
  for (let k = 0; k < length - 1; k++) {
    for (let i = k + 1; i < length; i++) {
      const s = a[i][k] / a[k][k];
      for (let j = k + 1; j < length; j++) {
        a[i][j] -= s * a[k][j];
      }
      b[i] -= s * b[k];
    }
  }
  for (let i = length - 1; i >= 0; i--) {
    for (let j = i + 1; j < length; j++) {
      b[i] -= a[i][j] * b[j];
    }
    b[i] /= a[i][i];
  }
}
 

参考サイト