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.
[https://webassembly.org](https://webassembly.org)


# なぜ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コンパイルにも欠点が存在した。

1. よく使うコードしかネイティブコードにならない
    →型情報の推定に統計処理が必要

2. 高速に動作するようになるまでにはリードタイムが必要
    →上記に同じ

3. 型の推定には失敗することがある
    →あくまでも統計上の推論であるため失敗することがある

立ち上がりが遅い、やり直しが発生する、コンパイルによって一時的に負荷が向上するといった事が起こる。


- JTIコンパイル
    - インタプリタでのプログラム実行時に、あらかじめ用意された（実行環境に依存しない汎用的な）中間コードを、プログラムの実行時点でプロセッサが実行可能な機械語（ネイティブコード）にコンパイルすること


## asm.jsの登場

そこでasm.jsが登場する。asm.jsはMozillaが研究開発したJavaScriptのサブセット。2013年に公開された。
asm.jsを一言で表すなら、

> JavaScriptをある制約に従って書くことで、型を明確にして事前コンパイル(AOTコンパイル)できるようにする技術

静的型付けにより、プログラムの実行を行うより前にネイティブコードへとコンパイルするAhead of Timeコンパイルが可能となる。これによりネイティブコードを高速にブラウザで実行可能。
トランスコンパイラ Emscriptenなどの登場により、C/C++などからもasm.jsにコンパイルが可能に。
asm.jsの登場により事前コンパイルができることでトータルの実行速度は速くなったが、JavaScriptのファイルサイズが増えるというデメリットがあった。

- ファイルサイズの増大による通信量の増加
- ファイルサイズの増大によるパージング(構文解析)の時間増加
- JavaScriptのサブセットなのでJavaScriptの制約から抜け出せない

これを解決するために、現在策定されているのがWebAssembly。

ちなみにasm.jsの開発は現時点で止まっている模様
[asm-js/validator](https://github.com/asm-js/validator)



参考：[Webブラウザで高速な演算を可能にする低水準言語asm.jsと、WebAssembly詳解ーJavaScript が動く仕組み](https://html5experts.jp/chikoski/18964/)

# WebAssemblyへ

冒頭でも述べたように、WebAssemblyとはブラウザでプログラムを高速実行するための
**「ブラウザ上で動くバイナリコードの新しいフォーマット(仕様)」**
である。

2015年6月17日に公表され、2017年11月にFirefox、Chrome、Safari、Edge等の主要なブラウザの全てに対応したと発表された。Google, Microsoft, Mozzila, Appleによって仕様が策定され開発が進められている。

C/C++やRust、Golang、TypeScriptなどからコンパイルが可能。


2種類のフォーマットが存在する。

- WASM ... バイナリフォーマット
- WAT/(WAST) ... 人間が WebAssembly を読んだり編集するための wasmのテキスト表現
    - テキストエディタ、ブラウザの開発者ツールなどで見せるために設計された中間表現

## Wasmはなぜ早いのか

### CPUの活用

asm.jsはJavaScriptとして処理できる形式でモジュールとその関数本体を定義していたため、その能力はJavascriptの表現できることに限定されていた。

一方でWebAssemblyは仮想的なハードウェアで動く低水準な命令の集まりとしてモジュールを定義されている。
これによりJavaScriptの表現能力に制限されず、CPUの機能をより十全に利用すること出来る。

### 起動の高速化

そもそも抽象構文木がバイナリ形式で与えられているおかげで、ネイティブコードを出力するために必要な処理の字句解析と構文解析の大半を省き、起動の高速化が可能となっている。

## Javascriptとの関係

WebAssemblyはJavaScriptの代替ではなく、JavaScriptを補完する目的で開発された。

JavaScriptからWebAssemblyの関数を呼び出したり、WebAssemblyからJavaScriptの関数を呼び出したり出来る。お互いになくてはならない存在(今のところは？）

基本的にはWebAssemblyで実装したモジュールをJavaScriptで呼び出すという形で利用される。
[WebAssemblyコードのロードと実行](https://developer.mozilla.org/ja/docs/WebAssembly/Loading_and_running)
※S2015 の import 文とまだ統合されていないため、インポートを使用してブラウザでモジュールをfetchする事は出来ない

WebAssembly側から直接Domを操作することは出来ない。そのため、WebAssemblyにコンパイル出来る各言語にJavaScriptのAPIを呼び出すWasm用のライブラリが開発されている。

- [Golang - syscall/js](https://tip.golang.org/pkg/syscall/js/)
    - Golang 1.11.0から標準パッケージに
- [Rust - rustwasm/wasm-bindgen](https://github.com/rustwasm/wasm-bindgen)
    - Rust向けのツールはいくつか存在する模様


## 想定ユースケース
ゲームや画像・動画などの高度な計算処理をブラウザ上で実行するために用いられる。

1. アプリ全てをWASMで実装する
    →C/C++で書かれたゲームアプリ等をWebに移植するための手段

2. WASMでほとんどを実装し、UIなどをWeb技術で実装する
    →画像認識エンジンや、動画像処理エンジンなどのC/C++資産をWebに移植

3. Webアプリケーションのうち、速度が必要な部分をWASMで実装する
    →バックエンドでRailsの速度を出したいとこをGoで置き換える的なことをフロントで行う


参考：[Webassembly.org - Use Cases](https://webassembly.org/docs/use-cases/)

## WebAssemblyの今と今後

現在、WebAssemblyは MVP (最小限の実用製品) の段階。
今後様々な機能が追加される予定。

- GCのサポート
    - オプショナルなので、使うかどうかはプログラマが選択できる。
    - 他言語で速く書きたい場合は、GCをオンにするなどの選択が出来るように
- Es-Moduleとして読み込めるように
- マルチスレッド対応？
- Domを操作するためのAPI追加？（Js競合しなって公式で言われたけどゆくゆくは競合するの？？）

[Features to add after the MVP](https://webassembly.org/docs/future-features/)
[Where is WebAssembly now and what's next? - Mozilla Hacks - the Web developer blog](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はGoogle, Microsoft, Mozzila, Appleなどが協力して開発しているのでそこは強みと言える。

参考：
[Non-Web Embeddings](https://webassembly.org/docs/non-web/)
[WASI](https://wasi.dev)
[WebAssemblyをWebブラウザ以外の実行環境へ。システムインターフェイスへのアクセスを可能にする「WASI」の策定開始。Mozillaが呼びかけNode.jsらが賛同](https://www.publickey1.jp/blog/19/webassemblywebwasimozillanodejs.html)


# eWasm
EthereumのEVMコードをEVMで実行するという仕組みから、Ethereum用のWebAssemblyのサブセットをeWASM VMで実行する仕組みに変える。

### メリット
- コントラクト実行の高速化
- WebAssemblyのエコシステムの活用

### 概要
[ewasm/design](https://github.com/ewasm/design)

FAQとか見てると、WASM以外にも検討されたものとかあって面白い
[ewasm/FAQ](https://github.com/ewasm/design/blob/master/faq.md)


Testnetは既に動いてる?
[http://ewasm.ethereum.org / ewasm!](http://ewasm.ethereum.org)

## その他 参考にしたもの
[GoでWebAssemblyに触れよう](https://golangtokyo.github.io/codelab/go-webassembly/?index=codelab#4)
[ゼロからはじめるWebAssembly入門(2017/01更新) - Qiita](https://qiita.com/OMOIKANESAN/items/1ffc06ef6283befc4355)
[WebAssembly: 「なぜ」と「どうやって」 [翻訳記事]](https://dev.to/nabbisen/webassembly--3385)