AssemblyScriptを使ってTypeScriptをWebAssemblyにコンパイルする
今回は、AssemblyScript を使って TypeScript(.ts)を WebAssembly(.wasm)にコンパイルし、それを Node.js で実行するやり方について紹介します。
最初に結論を言っておきます。Gaussの消去法で連立一次方程式を解くプログラムを使って、C から生成した WebAssembly と TypeScript から生成した WebAssembly の処理時間を比較したところ、TypeScript の方が C に比べ約40倍、処理時間がかかりました。ということで、配列を操作するようなプログラムの場合は、迷わず C から WebAssembly にコンパイルしてください。
注)C(.c)を WebAssembly(.wasm)にコンパイルするには、Emscripten か WebAssembly 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];
}
}
参考サイト
- AssemblyScript
- AssemblyScriptを使ってTypeScriptのコードを早くしよう
- TypeScriptでWebAssemblyを開発できるAssemblyScriptを試してみた
- NodeでWebAssemblyの速度を計る