WebAssembly調べてみた

こんにちは @k_mattun  です。

前々からWebAssemblyという言葉を聞く機会は多かったのですが、実際どんなもので何に利用するのか知らなすぎたので調べてみました。

なお、本記事は[All About Group（株式会社オールアバウト） Advent Calendar 2022](https://qiita.com/advent-calendar/2022/allabout)の3日目の投稿となります。

# WebAssemblyとは
<img width="400" alt="68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3533343833392f33366337653531632d303832372d346431372d313866372d6166343138313439343032662e706.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545198/bb4d6d31-3279-60c3-74bf-5612b6d04336.png">


プログラミング言語やライブラリの名称ではなく、ブラウザでプログラムを高速実行するためのバイナリコードの新しいフォーマット。

最近のウェブブラウザ上で動作する仕様で、様々なWebブラウザの差異を吸収してどこでもアプリケーションが軽快に動作する環境を整備することを目的としている。

- JavaScriptよりも基本的に高速
- C、C++、Rust、Go、TypeScriptなど幅広い言語が対応
- Chrome、Firefox、Edge、Safariなど主要ブラウザで対応

# WebAssemblyの目指しているもの

基本的に高いパフォーマンスを発揮するアプリケーションを実行可能にし、特定の言語やプラットフォームに依存しない、汎用的な運用を目指している。

WebAssemblyの仕様書にはDesign Goalsとして下記の７項目がある。

|目標  |概要  |
|---|---|
|高速  | 最新のすべてのハードウェアに共通の機能を利用して、ネイティブ コードに近いパフォーマンスを発揮する  |
|安全  |コードは検証され、メモリセーフなサンドボックス環境で実行され、データの破損やセキュリティ違反を防ぐ  |
|適切に定義されている | 形式的かつ非形式的に容易に説明できる方法で、”有効なプログラム”とその”挙動”を定義する。 |
|ハードウェアに依存しない | 最新のすべてのアーキテクチャ、デスクトップまたはモバイル デバイス、組み込みシステムで同様にコンパイルできる |
|言語に依存しない |  特定の言語、プログラミング モデル、またはオブジェクト モデルを特別扱いしない |
|プラットフォームに依存しない | ブラウザに埋め込んだり、スタンドアロン VM として実行したり、他の環境に統合できる |
|オープン | プログラムは簡単かつ汎用的な方法で環境と相互運用できる |

# JavaScriptとの関係性

WebAssemblyはJavaScriptの代替ではなく、JavaScriptが苦手な領域を保管する目的で開発されている。

そのためJavaScriptとの関係性も高く、相互に関数を呼び出し合ったりもする。
基本的にはWebAssemblyの実装をJavaScript側で呼び出す利用ケースが殆んど。

JavaScriptの代替ではない証として、WebAssemblyで直接Domを操作することはできない。

# WebAssemblyとJavaScriptの使い分けについて
調べてみると以下のように分類されている。

|ケース  |利用技術  |
|---|---|
|計算負荷の高いアルゴリズム  |WebAssembly  |
|Dom操作  |JavaScript  |
|ゲーム(CPUを集中的に利用する) | WebAssembly |
|ウェブサイト、ブログ | JavaScript |

https://www.assemblyscript.org/frequently-asked-questions.html#frequently-asked-questions

WebAssemblyを使うメリットとしては主に以下がありそう

- JavaScriptではできなかった負荷の大きな処理をブラウザで実行できる
- C、C++など既存のソースコードを様々なブラウザで実行できる、移植性
- フロントとバックの処理を同じ言語で記述できる

# WebAssemblyはなぜ早いのか

JavaScriptはWebブラウザが搭載するJavaScript処理エンジンがパース処理を行いバイトコードに変換。
いわゆるインタプリタ言語で逐次処理が行われている。

WebAssemblyはバイナリファイルにコンパイルしたファイルをWebブラウザが直接読み込んで実行することもあり、パース処理や最適化処理が施された状態で実行されるため、JavaScirptよりも実行速度が早いと言われている。

<img width="800" alt="スクリーンショット 2022-12-02 221941.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545198/2a88d2d0-1997-b634-47a4-ea97fe8c55a4.png">

他にはJavaScriptが動的型付けなため、実行毎に変数の型を決める作業が発生する。
逆にWebAssemblyは静的型付けであるため、その作業が発生せず実行速度が速くなる。


# WebAssemblyの実用例

## Google Earth

<img width="300" alt="ダウンロード.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545198/dc14254c-fa3e-0690-585f-f018e1bc6fb6.png">

GoogleEarthは今でこそ様々なブラウザで利用できるようになったが、初期の頃はChromeでしか利用できない状況だった。
主要なブラウザにWebAssemblyの仮想マシンが導入されたことから、各ブラウザへの対応が進んだよう。

## Google Meet

<img width="300" alt="Google_Meet_icon_(2020).svg.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545198/7e5816a7-3038-676b-3271-53b4a67df875.png">

リモートワークということで弊社でも頻繁にGoogleMeetでオンラインMTGを行っている。
Meetの機能として背景ぼかし機能がリリースされたが、動画の各フレームから背景を抽出&ぼかしをかける処理はある程度大きな負荷となる。
それをブラウザ上で実現するためにWebAssemblyが利用されている。

こちらに関しては、Googleがブログをだしている。

https://ai.googleblog.com/2020/10/background-features-in-google-meet.html

## その他

以下に利用されているサービスが一覧で見れる。
UnityやOpenCVなど有名なものも多く利用している。

https://madewithwebassembly.com/

また公式からも幅広い使い方が提案されている。

https://github.com/WebAssembly/design/blob/main/UseCases.md

# Wasmerの登場
<img width="400" alt="og-image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545198/37b48903-cda6-f54b-87e9-c862dd8dde4f.png">

WasmerはWebAssemblyランタイムの一つで、WebAssemblyを実行することができる。

Dockerはコンテナ仮想化で任意の言語・フレームワークで開発されたコードを実行する環境を実現している。
それと同じ感覚で、WasmerはWebAssemblyを任意の環境でネイティブに近いパフォーマンスでWebAssemblyを動作させることが可能とする。

コンパイル後のターゲットをWebAssemblyにするとWebAssemblyランタイムをインストールしているOSならどんなOSでもアプリケーションを動かせるようになる。

WebAssemblyランタイム技術は他にもあり、wasmtimeやLucetなどがあるよう。

チュートリアルがあるようなので、気になる方は是非。

https://docs.wasmer.io/

# まとめ
WebAssemblyってなんだろって感じで調べてみましたが、思っていたよりも可能性の高い技術で今後伸びてきそうだなと感じました。
プロダクションの実用実績も多いのと、サーバーサイドでの実行が可能になったことで新たな分野での利用が検討されていたりで、どこまで伸びていくのかとワクワクしてしまいます。

もともとはJavaScript以外のプログラミング言語によるコードを実行するためのバイナリフォーマットとして登場していましたが、WebAssmblyアプリケーションをKubernetesのPodとして実行できるようにする[「Krustlet」](https://krustlet.dev/)が登場したりと、確実に普及してきています。

最近出てきたばかりではなく、数年前から話題に上がっていた技術だったので、日頃からもう少し技術に関してキャッチアップしていきたいなと思いました。軽く調べるだけで既に沢山の情報が公開されているので、手元で色々ためしてそれをまた記事にできたらと思います。


# 参考

- https://xtech.nikkei.com/atcl/nxt/column/18/01818/101400002/
- https://mixil.mixi.co.jp/people/12242
- https://www.assemblyscript.org/frequently-asked-questions.html#frequently-asked-questions
- https://webassembly.github.io/spec/core/intro/introduction.html#design-goals
- https://docs.wasmer.io/
- https://zenn.dev/koduki/articles/f1b342079788be#%E3%81%BE%E3%81%A8%E3%82%81
- https://www.publickey1.jp/blog/21/kuberneteswebassemblykrustletcncf.html
- https://rustwasm.github.io/book/introduction.html#who-is-this-book-for
- https://thinkit.co.jp/article/19689
- https://thinkit.co.jp/article/19690