コンテンツへスキップ

WebAssemblyをRustで試す

by : 2017/12/19

Webでより高速なWebアプリケーションを実行するための仕組みとして注目されているのがWebAssemblyです。バイナリファイルであり、あらかじめコンパイルされていることでソースコードを簡単に見られてしまうJavaScriptの欠点を補うことができます。

現在、CやC++で書くことが多いWebAssemblyですが、Rustも着実に対応が進んでいます。ついに Rust単体でWebAssemblyをコンパイルする(Emscripten無し) にあるようにRustだけでWebAssembly向けにコンパイルができるようになりました。

今回はそちらのレビューになります。

RustはC/C++に比べると分かりやすい言語だと思います。型推測もあり、スクリプト言語のように書けます。今回はJavaScriptとの速度比較用に、以下のようなコードにしてみました。時間をかけるため、あえてループを繰り返しています。

#[no_mangle]
pub fn sum(a: i32) -> i32 {
let mut total = 0;
for x in 0..a {
total += x;
for y in 0..a {
total += y;
}
}
total
}

view raw
index.rs
hosted with ❤ by GitHub

これをコンパイルします。

rustc +nightly –target wasm32-unknown-unknown -O main.rs –crate-type=cdylib

view raw
index.sh
hosted with ❤ by GitHub

その結果 main.wasm というファイルが生成されます。

呼び出し方

WebAssemblyは script タグで呼び出せる訳ではありません。Ajaxで取得する必要があります。以下の処理で sum という関数が使えるようになります。

var sum = null;
fetch('main.wasm')
.then((response) => response.arrayBuffer())
.then((bytes) => WebAssembly.instantiate(bytes, {}))
.then((results) => {
const instance = results.instance;
sum = instance.exports.sum;
});

view raw
index.rs
hosted with ❤ by GitHub

sum 自体は Native Code と判断されます。実行は普通の関数と変わりません。

> sum(10)
<- 495

view raw
index.txt
hosted with ❤ by GitHub

JavaScriptとの速度比較

JavaScriptでは以下のようなコードで試しました。

total = 0;
for (var x = 0; x < i; x++) {
total += x;
for (var y = 0; y < i; y++) {
total += y;
}
}
console.log(total);

view raw
index.js
hosted with ❤ by GitHub

それぞれ3回繰り返した平均値です(単位は ms)。

回数 Rust JavaScript
100 190 513
1,000 165 3979
2,000 163 36593
5,000 172 337251
10,000 209 1427188

WebAssemblyの実行結果は回数に殆ど関係しませんでした。10,000回繰り返した時にも275/176/177msといった数字で、もっと回数の少ない時と変わりません。逆にJavaScriptは処理回数によってリニアに処理時間が延びている印象です。

WebAssemblyの欠点

現状のWebAssemblyはDOMやWeb API、GCに対応していません。そのため利用範囲が限られてしまうでしょう。将来的にはこれらのAPIにも対応が予定されています。


Rust自体は学習しやすい言語だと思います。それによって現状のWebを高速化できるので今後に期待した技術です。現状についてはJavaScriptから呼び出される補助的な技術ですが、将来的にはC/C++/Rustをはじめ、多くの言語でWebアプリケーションが開発できるようになるでしょう。

プログラミング言語 Rust

From → HTML5

コメントは受け付けていません。

%d人のブロガーが「いいね」をつけました。