WebAssemblyチャレンジ

まだ何かができるという状態ではないのだが。

WebAssemblyとは

AppleMicrosoftGoogleMozillaが力を合わせて開発しているブラウザ用のバイナリフォーマットで、フォーマットっていうか、VMの命令セットと挙動の定義みたいな。バイナリフォーマットはwasmと呼ばれていて、これをブラウザで読み込んで実行することができる。大手ベンダが取り組んでいるのでメジャーなブラウザやブラウザじゃない何かで実行することができるようになるだろう、と言われている。
主な狙いは最近JavaScriptのコードが大きくなっていることに伴うダウンロード、パース、コンパイルの時間短縮で、よく言われる実行速度の向上ではない。んでも最近CやRustで書いたコードをWebAssemly化したらJavaScriptより3倍速くなったという記事が現れて、まあ、そもそも高速な言語なんだからそりゃ速くなるよね、って感じ。今はできないがJavaScriptコンパイルしてWebAssemly化したら実行速度は言うほど変わらないんじゃないかと思っている。とはいえ高速な言語を高速に実行できるというのはすごく良い。

環境とか

現状ではLLVMでCやRustをLLVM IRに変換→wast(WebAssemblyのテキスト表記。S式)に変換→wasm(バイナリ)に変換とやってJavaScriptで読み込んで実行という手順になる。正式リリース版で実行できるブラウザはこれを書いている今現在ではFireFox52とChrome57。
LLVMよくわかんないしツールいっぱいビルドしたりするみたいなのでそこいらへんは諦めて、うちのChromeで人様の作ったバイナリを実行するぐらいならできるだろう。

準備

Julia で WebAssembly - Qiitaの人が作ったものを拝借する。githubこちらで、sample.wasmとindex.htmlをダウンロードする。sample.wasmが足し算する関数が入ったバイナリファイルである。こんなの。

00 61 73 6D 0D 00 00 00 01 07 01 60 02 7F 7F 01
7F 03 02 01 00 04 04 01 70 00 00 05 03 01 00 01
07 1C 02 06 6D 65 6D 6F 72 79 02 00 0F 6A 75 6C
69 61 5F 61 64 64 5F 37 31 33 36 30 00 00 0A 09
01 07 00 20 01 20 00 6A 0B

ちなみに最初の4バイトが\0asmとなるのがマジックヘッダで、そのあとの4バイトがバージョン(リトルエンディアン)。このファイルはバージョン0x0dとなっていて、これは開発最終版のバージョンであり、このファイルは正式リリースのバージョン(0x01)とは違うのでChrome57では動かない。動かすためには開発版のChrome Canaryが必要なのだが、そんなもん用意するのも面倒なので、バイナリエディタでおもむろに0x0dを0x01に書き換える。ちなみに開発最終版と正式版はとりあえずこのレベルではフォーマットに違いが無い。と思う。バイナリフォーマットについてはWebAssembly binary encoding version 0x1 - Qiita公式を参照。

動かしてみる

index.htmlとsample.wasmを置いたところにRubyのコードを一緒に置いて、

require 'webrick'

srv = WEBrick::HTTPServer.new({
  DocumentRoot:   './',
  BindAddress:    "localhost",
  Port:           8000,
})

srv.start

これを起動してChrome57でhttp://localhost:8000/index.htmlをアクセスすると、

てな感じにAdd!ボタンで足し算ができるようになる。この足し算の計算はWebAssembly側(元ネタを作った人はJuliaで構築したらしい)で行っている。

思ったこと

自分でやったことと言えば0x0dを0x01に書き換えただけなのでぶっちゃけ何もしていないのだが、もうちょい何かやってみたい。LLVMうんぬんでツールチェインを揃えるのはやっぱり面倒で、バイナリフォーマットもたいして難しくないので自前でwasmを出力できる何かを作ったほうが簡単かな〜とか考えているところ。