WebAssemblyとは
こんにちは、HashHubエンジニアの白井です。
本日のTech Blogは「WebAssemblyについてゆーるく調べてみた」です!
ブロックチェーン業界にいる方であれば、Ethereum 2.0ではWebAssembly(WASM)でコントラクトが書けるということを聞いたことがあるかと思います。
今回はブロックチェーンのことは少なめで、そもそもWebAssemblyって何ってことを説明しようと思います。
WebAssemblyとは
プログラミング言語やライブラリの名前ではなく、ブラウザでプログラムを高速実行するための、「ブラウザ上で動くバイナリコードの新しいフォーマット(仕様)」です。
Google, Microsoft, Mozzila, Appleによって仕様が策定され開発が進められています。
WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.
なぜWebAssemblyが必要なのか
ブラウザ上でプログラムを実行するということの変化
Chrome / Firefox / Edge / Safari いずれにおいても、ブラウザ上でプログラムを実行したいときにはJavaScript が使わてきました。
JavaScriptが登場した当初、その役割はHTMLに飾りつけをする程度でした。
しかしAjaxを始めとしたJS界隈の発展や、HTML5の登場、UnityやWebGL (Web Graphics Library)などの登場により、その役割は大きくなります。そして、様々な処理に活用される中で、マシンパワーの劣るモバイル端末ではその遅さが目立つようになりました。
こうしてJavaScriptも実行速度が求められるように変化していったのです。
- HTML5
<video>や<audio>タグなどの簡単にメディアを埋め込めるタグが追加された。
<header>や<footer>などの文書の構造を表すタグが追加された。
HTML4以前では実現することが難しかった高度な機能を実現するための様々なAPIが新たに追加された。
- WebGL (Web Graphics Library)
今までネイティブアプリにしかできなかったGPUへのアクセスを可能にするグラフィクスAPI。HTML5のcanvas要素を通してブラウザだけで3Dゲームを実行可能にする。
- Unity
Web技術の発展とAPIの整備の結果、Game、Virtual Reality(VR)、画像認識などの少し前まではネイティブでの実装しか実現不可能だった種類のアプリケーションもWebブラウザをランタイムとするJavaScripで実装されるようになった。UnityなどのゲームエンジンなどにもJavaScriptが採用される。
Just In Timeコンパイルの採用
様々な役割に用いられるようになったJavaScriptは、Just In Timeコンパイルという方式を採用することで7倍程度の高速化が行わました。
しかし、JavaScriptが動的型付け言語であるが故に、JITコンパイルにも欠点が存在します。
- よく使うコードしかネイティブコードにならない
→型情報の推定に統計処理が必要
- 高速に動作するようになるまでにはリードタイムが必要
→上記に同じ
- 型の推定には失敗することがある
→あくまでも統計上の推論であるため失敗することがある
立ち上がりが遅い、やり直しが発生する、コンパイルによって一時的に負荷が向上するといった事が起こります。
- JTIコンパイル(実行時)
インタプリタでのプログラム実行時に、あらかじめ用意された(実行環境に依存しない汎用的な)中間コードを、プログラムの実行時点でプロセッサが実行可能な機械語(ネイティブコード)にコンパイルすること
asm.jsの登場
そこでasm.jsが登場します。asm.jsはMozillaが研究開発したJavaScriptのサブセット。2013年に公開されました。
asm.jsを一言で表すなら、
JavaScriptをある制約に従って書くことで、型を明確にして事前コンパイル(AOTコンパイル)できるようにする技術
です。
静的型付けにより、プログラムの実行を行うより前にネイティブコードへとコンパイルするAhead of Timeコンパイルを行えます。これによりネイティブコードを高速にブラウザで実行可能です。
asm.jsの登場により事前コンパイルができることでトータルの実行速度は速くなりましたが、JavaScriptのファイルサイズが増えるなどのデメリットが残りました。
- ファイルサイズの増大による通信量の増加
- ファイルサイズの増大によるパージング(構文解析)の時間増加
- 高速化されたとはいえ、asm.jsはあくまでもJavaScriptのサブセットなので、JSの制約を超えられない。
これを解決するために、現在策定されているのがWebAssemblyです。
ちなみにasm.jsの開発は現時点で止まっています。
参考:
WebAssemblyへ
冒頭でも述べたように、WebAssemblyとはブラウザでプログラムを高速実行するための
「ブラウザ上で動くバイナリコードの新しいフォーマット(仕様)」
です。
2015年6月17日に公表され、2017年11月にFirefox、Chrome、Safari、Edge等の主要なブラウザの全てに対応したと発表されました。Google, Microsoft, Mozzila, Appleによって仕様が策定され開発が進められています。
LLVMのコンパイルターゲットとして正式に迎えられ、C/C++やRust、Golang、TypeScriptなどからコンパイルが可能です。
WebAssemblyには2種類のフォーマットが存在します。
- WASM … バイナリフォーマット
- WAT/(WAST) … 人間が WebAssembly を読んだり編集するための wasmのテキスト表現
WATの方は、テキストエディタ、ブラウザの開発者ツールなどで見せるために設計された中間表現となります。
Wasmはなぜ早いのか
CPUの活用
asm.jsはJavaScriptとして処理できる形式でモジュールとその関数本体を定義していたため、その能力はJavascriptの表現できることに限定されていました。
一方でWebAssemblyは仮想的なハードウェアで動く低水準な命令の集まりとしてバイナリフォーマットでモジュールを定義します。
これによりJavaScriptの表現能力には制限されないので、CPUの機能をより十全に利用することが出来、ハッシュや暗号アルゴリズムなどの計算の程度高速化や、JavaScriptが扱えないCPUに対する命令を扱うことが出来ます。
起動の高速化
抽象構文木がバイナリ形式で与えられているおかげで、ネイティブコードを出力するために必要な処理の字句解析と構文解析の大半を省き、起動の高速化が可能となっています。
Javascriptとの関係
WebAssemblyはJavaScriptの代替ではなく、JavaScriptを補完する目的で開発されました。
JavaScriptからWebAssemblyの関数を呼び出したり、WebAssemblyからJavaScriptの関数を呼び出したりして実際には動きます。
基本的にはWebAssemblyで実装したモジュールをJavaScriptで呼び出すという形で利用されますが、現在は、ES2015のimportなどには対応しておらず、特殊な関数を使う必要があります。
index.html// goで書かれたwasmを読み込む時に必要なjsファイル
<script src="wasm_exec.js"></script><script>
// main.wasmにビルドされたGoのプログラムを読み込む
const go = new Go();let mod, inst;// WebAssembly Moduleをコンパイルしてすべての関数を含むインスタンスを作成WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then((result) => {
mod = result.module;
inst = result.instance;...});</script>
ポイントとしては、WebAssembly側から直接DomやWebAPIを操作することは出来ないということです。(今のところは?→https://developer.mozilla.org/ja/docs/WebAssembly/Concepts)
また、WebAssemblyにコンパイル出来る各言語にJavaScriptのAPIを呼び出すWasm用のライブラリが開発されています。
想定ユースケース
ゲームや画像・動画などの高度な計算処理をブラウザ上で実行するために用いられることが想定されています。
- アプリ全てをWASMで実装する
→C/C++で書かれたゲームアプリ等をWebに移植するための手段
- WASMでほとんどを実装し、UIなどをWeb技術で実装する
→画像認識エンジンや、動画像処理エンジンなどのC/C++資産をWebに移植
- Webアプリケーションのうち、速度が必要な部分をWASMで実装する
→バックエンドでRailsの速度を出したいとこをGoで置き換える的なことをフロントで行う
WebAssemblyの今と今後
現在、WebAssemblyは MVP (最小限の実用製品) の段階です。
各ブラウザで実際に動かすことは出来ますが、機能は最小限で発展途上です。
今後様々な機能追加が予定されています。
- GCのサポート
- Es-Moduleとして読み込めるように
- マルチスレッド対応?
一点気になったこととしては、下の参考記事にもあるのですが、ゆくゆくは直接Domを操作出来る機能の追加も想定しているとのこと。
前述したとおり、Javascriptとは競合しないと公式では説明されていますが、最終的にはどうなるんでしょうね。
参考:
https://hacks.mozilla.org/2017/02/where-is-webassembly-now-and-whats-next/
WASMのWeb領域以外への活用
WebAssemblyにファイルやネットワーク、メモリなどのシステムリソースへの安全なアクセスを可能にするAPIの標準仕様「WASI」WebAssembly System Interfaceの策定をMozilaが進めています。
Javaが掲げていた”Write Once, Run Anywhere”の代替になりそうですね。JavaがOracleの所有物なのに対してWasmは多くテックジャイアント達が協力して開発しているのでそこは強みと言えるでしょう。
参考:
https://www.publickey1.jp/blog/19/webassemblywebwasimozillanodejs.html
eWasm
最後にeWasmについても少しだけ。
Ethereum 2.0への移行とともに、EVMコードをEVMで実行するという仕組みから、Ethereum用のWebAssemblyのサブセットをeWASM VMで実行する仕組みに変えるという提案がなされました。
eWASMを採用することでめちゃくちゃざっくりですが、以下のメリットがあります。
- コントラクト実行の高速化
- WebAssemblyのエコシステムの活用
超ざっくりです(理解出来ていない…笑)
基本的なeWASMのデザインについてはこちらで確認できます。
FAQとかみてみると、wasm以外にも検討されてたものが確認出来て面白いですね。
eWASM版のTestnetは既に動いてるんですかね?(そこまで調べられなかった…)
はい、以上です。
今回は、ブロックチェーン要素少なめでWebAssemblyについて解説しました。
eWASMについては深く調べられなかったので近いうちにまた勉強しようと思っています。
WebAssemblyについては、理解の入り口には立てた気がします。Rustを使ってフロントエンドを構築するという面白そうなフレームワークもあるのでこういったの近いうちに試してみたいですね。
お知らせ
■ステーキング事業の提供を始めました!
7月からHashHubでは、Cosmos,Tezos,IOSTの3つのトークンをステーキング出来るサービス「Sanka Network」を提供し始めました。本サービスのご利用をご検討の方は、下記のWEBサイトからお問い合わせください。
Sanke Network:https://www.sanka.network/
■HashHubでは下記のポジションを積極採用中です!
・コミュニティマネージャー
・ブロックチェーン技術者・開発者
・ビジネスディベロップメント
詳細は下記Wantedlyのページをご覧ください。
Wantedly:https://www.wantedly.com/companies/hashhub/projects
■HashHubでは入居者募集中です!
HashHubは、ブロックチェーン業界で働いている人のためのコワーキングスペースを運営しています。ご利用をご検討の方は、下記のWEBサイトからお問い合わせください。また、最新情報はTwitterで発信中です。
HashHub:https://hashhub.tokyo/
Twitter:https://twitter.com/HashHub_Tokyo