2017/01時点の情報に更新しました。
今後の展望が期待されているWebAssembly(以下wasm)について、
事前知識ゼロの状態から調べて入門してみた記事です。
# 目次
・wasmとは
・wasmが生まれた経緯
・wasmバイナリの作成方法
・実際に動かしてみる
・wasmの感想/わかったこと
・利用シーン
・参考URL
# wasmとは
WebAssemblyは、プログラミング言語やライブラリの名前ではなく、
**「ブラウザ上で動くバイナリコードの新しいフォーマット(仕様)」**のことです。
wasmは、**「Webアプリケーションの高速化」**を目的として、
各ブラウザベンダー (Google,Microsoft,Mozzila,Apple)が協力して策定中です。
既にChrome,FireFox上であればwasmに準じたバイナリコードを実行することができます。
# wasmが生まれた経緯
JavaScriptも実行速度が求められる時代になった
まず「JavaScriptは遅い」と言われる原因の1つに
JavaScriptが動的型付けの言語だからというのが挙げられます。
動的型付けということは、
変数が数値になったり文字列になったりと、実行直前まで型が定まらないということです。
これのせいで、JavaScriptなどの動的型付け言語は、実行前にコンパイルすることができず、
インタプリタ(逐次実行)方式によって逐一機械語に翻訳されて動きます。
そのためコンパイラ言語と比較して速度の面で大きく劣ります。
JavaScriptが登場した当初は、HTMLに飾りつけをする程度の用途だったので問題ありませんでしたが、
Ajaxを始めとしたJS界隈の発展やHTML5の登場、UnityやwebGLなどの登場により、
特にマシンパワーの劣るモバイル端末ではその遅さが目立つようになりました。
こうしてJavaScriptも実行速度が求められるようになってきたようです。
高速化の策~asm.jsからwasmへ~
JavaScriptエンジンの性能向上もだんだん頭打ちとなって行く中で、
先ほどの「動的型付けなのでコンパイルできない」問題を解決する方法として
2013年頃にasm.jsというJavaScriptのサブセット(部分集合)の技術が生まれます。
asm.jsは、JavaScriptをある制約に従って書くことで、
型を明確にして事前コンパイル(AOTコンパイル)できるようにする技術です。
事前コンパイルができることでトータルの実行速度は速くなり
UnityやゲームエンジンのUnrealEngineなどにも採用されましたが、
JavaScriptのファイルサイズが増えるというデメリットがあり、
- ファイルサイズの増大による通信量の増加
- ファイルサイズの増大によるパージング(構文解析)の時間増加
といった課題が残りました。
そこでasm.jsの代替案としてwasmが登場します。
JavaScriptのコードではなくバイナリコードで扱うことで、
ファイルサイズを大幅に小さくすることができ、これらの問題を解決しています。
wasmバイナリの作成方法
asm.jsと同様、自分の手でwasmのバイナリを書くのは無理なので、
何かしらの方法でソースコードから生成する必要があります。
現状では前述のasm.jsと同様、OSSのコンパイラ基盤 LLVM を使います。
(2017/01現在では、C,C++,rustと言った言語がwasmバイナリに変換可能です)
LLVMは、フロントエンドとバックエンドにコンパイラが分かれており、
内部で中間表現(LLVM IR)に変換することで、指定の形式にコンパイルすることができます。
実際に動かしてみる
2017/01現在では、C,C++でもRustでもバックエンドのコンパイラにはEmscriptenを使うと良いです。
このあたりは日々変化しており、Rustではバージョン1.14からコマンド1つでasm.jsやwasmへのコンパイルが可能になりました。
- Rust言語、asm.jsやWebAssemblyをサポートへ。WebブラウザやNode.jsで実行可能に
http://www.publickey1.jp/blog/17/rustasmjswebassemblywebnodejs.html
EmscriptenはLLVMをベースにC/C++のコードからJavaScriptやasm.jsのコードを生成できるコンパイラです。RustはEmscriptenが対応するLLVM IR(LLVM中間表現)を生成することでEmscriptenに対応。一方でEmscriptenはasm.jsだけでなくWebAssemblyを生成する機能の開発中です
下記の記事がとても参考になります。
-
RustからWebAssemblyにコンパイルしてみる
http://suzumi.hatenablog.com/entry/2017/01/05/180405 -
Rust から WASM32 を出力するための準備
http://qiita.com/chikoski/items/6c9f24dc4a825c437e78 -
Rustは何が新しいのか(基本的な言語機能の紹介)
http://imoz.jp/note/rust-functions.html
また、HelloWorld程度のサンプルでは高速化は実感できませんが、
asm.jsとwasmのデモサイトがあるので試してみてください。
(2017/01現在はリンク先の説明に従ってブラウザの設定を変更する必要があります)
Angry Bots Demo
http://webassembly.org/demo/
wasmの感想/分かったこと
- 日々着実に進化しており環境が整いつつある。もう少し様子を見たい。
- FireFoxとChromeの対応が早い。IE/Edgeとsafariも頑張ってほしい。
- wasmへのコンパイルは少々面倒だが、Rustのように言語側が対応していくだろう。
- LLVM自体のビルドに数時間がかかる。
- 実際に仕事で使う場合、テストとかデバッグとかどうするんだろう…?
- 部分的な処理速度向上のためには十分使えると思う。
- 好きな言語で作ってブラウザで動かせる時代になってほしい。
wasmの利用シーン
ざっと下記のような用途に使われそうかなと思います。
- 他言語で書かれた既存プログラムの流用
- 部分的な処理の高速化
- ブラウザゲームや、ブラウザ上でのVRやAR
- ブラウザ上での画像処理/動画処理
- ストリーミング配信
wasmユースケース
https://github.com/WebAssembly/design/blob/master/UseCases.md
これからもブラウザの対応や、言語側の対応など目が離せません。
今後の進化に期待したいです。
参考URL
asm.jsの基本的な使い方・まとめ
http://defghi1977.html.xdomain.jp/tech/asmjs/asmjs.htm
asm.jsとWebAssemblyって実際なんなの?
http://www.slideshare.net/likr/asmjswebassembly
Mozilla Japan ブログ - WebAssembly が 1 つのマイルストーンを達成しました
https://www.mozilla.jp/blog/entry/10539/