RustからWebAssemblyを作成する


#目的
①WebAssemby(wasm)とは何かを知る
②RustからWebAssemblyへの変換方法を知る
③WebAssemblyが本当に高速なのかを知る


#方法
WebAssemblyは本当に高速かどうかを調査するために以下のようなマンデルブロ集合を計算、描画するのにかかる時間を計測した。
wasm onlyとwasm + js(計算はwasm,描画はJavascript)、JavaScript Onlyの３パターンで比較。
canvasのサイズは1200*1200。1000回試行を平均。
[マンデルブロ集合]
(https://azisava.sakura.ne.jp/mandelbrot/definition.html)の実装は[実践Rustプログラミング入門]
(https://www.amazon.co.jp/%E5%AE%9F%E8%B7%B5Rust%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%85%A5%E9%96%80-%E5%88%9D%E7%94%B0-%E7%9B%B4%E4%B9%9F/dp/4798061700)を参考に行った。

ブラウザのバージョン
Cromium :92.0.4515.159
Microsoft Edge: 92.0.902.78 
Firefox：91.0.1 

PC環境
プロセッサ：Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz
RAM：8.00 GB

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/080a8d6d-a099-24aa-32ad-e92eacbaa511.png)

#結果
Firefoxは計算も描画もjavascriptの場合より速い。
Microsoft Edgeは同程度の速度。
ChromeはJavascriptの方が高速。
[実践Rustプログラミング入門]
(https://www.amazon.co.jp/%E5%AE%9F%E8%B7%B5Rust%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%85%A5%E9%96%80-%E5%88%9D%E7%94%B0-%E7%9B%B4%E4%B9%9F/dp/4798061700)でも同じ傾向の結果が記載されていた。
FirefoxもRustもWebAssemblyもMozilla社が開発しているため親和性が高いのだろうか？
とにかく、JavascriptよりもWebAssemblyの方が高速とは必ずしも言えなさそう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/fba89601-7297-9c47-97a8-279212962fb3.png)

[フィボナッチ数列の場合](https://qiita.com/umamichi/items/c62d18b7ed81fdba63c2)

#WebAssemblyとは？
[WebAssemblyとは？メリットはこちらを参照]
(https://developer.mozilla.org/ja/docs/WebAssembly/Concepts)

###使ってみての感想
メリット：C/C++/Rustコードを簡単にWEB上で動かせる。
デメリット：WebAssemblyへのコンパイルが遅い。Hello WorldでもCのコンパイルの10倍以上時間かかっている気がする。
　　　
###コンパイルの仕組み
C/C++はLLVM IRを経て、Clangによりアセンブリコードになり、EmscritptenというコンパイラによりWebAssemblyテキストコード（.wast)、最後にWebAssemblyのバイトコードとなる（.wasm)。
Rust,Go,AssemblyScriptは直接wasm形式にコンパイルできる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/6837c620-ec82-7ddb-c6a3-dcafcff93832.png)

###対応ブラウザと互換性
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/92243b52-8eac-4070-86db-b00e3d503cf8.png)

[リンク](https://developer.mozilla.org/ja/docs/WebAssembly)


#RustからWebAssemblyへの変換方法を知る
[参考](https://developer.mozilla.org/ja/docs/WebAssembly/Rust_to_wasm)


###環境構築
環境構築に必要なのは主に3つ。
1.JavaScriptのパッケージ管理ツールnpm
[参考](https://qiita.com/TsutomuNakamura/items/7a8362efefde6bc3c68b)

2.プロジェクトをテンプレートから作成するcargo-generate
以下のコマンドでインストール

```
cargo install cargo-generate
```

```
cargo generate --git https://github.com.rustwasm.wasm-pack-template
```
でテンプレートプロジェクトを作成する。wasm開発用の定型ファイル群を含んだプロジェクトが作成される。

3.wasm-packのインストール
Rustからwasmへのビルド、Rust-wasm-JavaScriptの橋渡しをするラッパーを作成してくれる。

```
curl https://rustwasm.github.github.io/wasm-pack/installer/init.sh -sSf | sh
```

###ビルド
ビルドの前にテンプレートプロジェクトに作成されたsrcファルダ内のRustファイルで適当な関数を実装する。

```
wasm-pack build
```

pkgフォルダが作られ、wasmファイルがその中に作られる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/04cd4442-01a9-82aa-20b0-af612d5e46fa.png)

###Webアプリ準備
```
npm init wasm-app www(好きなフォルダ名）
```

htmlやhtmlの中から実行するscriptが作られる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/67bd1a64-7cae-5e9a-b704-e9aaa344ee07.png)

```
npm install
```
Package.jsonに記載されている依存パッケージのインストールを行ってくれる

###サーバーの起動
```
npm run start
```

localhostにjavascriptから呼ばれたRustの関数が実行される。

###全体像
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/1dceeb98-5df1-3c39-4b11-b5b5bd4a7f39.png)

###デバッグで流れを追ってみる
wasmの中まで実行されていることは分かったが、流れはいまいち行ったり来たりで良くわからなかった。
デバッグが大変そう...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/cdcc96ea-2aa0-7d07-59d1-6b5be7414faf.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/71925c3b-830f-ab0a-c8d0-9f1550224d14.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/ae445d62-4a02-1b4a-5ced-5b82327827c3.png)