概要をつかんで遊ぶWebAssembly

# この記事の目的

- WebAssemblyの概要を理解する
- WebAssemblyのデモで遊ぶ

# WebAssemblyとは

ウェブブラウザ上で動的処理を実現する手段として，JavaScriptがデファクトスタンダードなことは皆さんご存知のとおりです．一方，多くの主要ブラウザでは，2017年頃からもう一つの実行環境が搭載されています．それが，**WebAssembly**です．WebAssemblyはJavaScriptでは実現が難しい，ネイティブレベルの実行速度を実現するために導入されました[^1]．一方，[公式FAQ](https://webassembly.org/docs/faq/) が（また[Google](https://developers-jp.googleblog.com/2023/05/webassembly.html)や[Mozilla](https://developer.mozilla.org/ja/docs/WebAssembly/Concepts#webassembly_%E3%81%AF%E3%81%A9%E3%81%AE%E3%82%88%E3%81%86%E3%81%AB%E3%82%A6%E3%82%A7%E3%83%96%E3%83%97%E3%83%A9%E3%83%83%E3%83%88%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E3%81%AB%E9%81%A9%E5%90%88%E3%81%99%E3%82%8B%E3%81%AE%E3%81%8B)が）強調しているように，WebAssemblyはJavaScriptの置き換えを企図しているわけではありません．JavaScriptはUI，WebAssemblyは高速処理と，互いに補い合うことを目的に開発されています．実際，これら二つの環境は隔離されて存在しているわけではなく，JavaScriptからWebAssemblyで書かれた機能をロードして呼び出すことができます（[WebAssembly コードの読み込みと実行](https://developer.mozilla.org/ja/docs/WebAssembly/Loading_and_running)）．この連携は現在のところひと手間かかりますが，将来的にはJavaScriptの`import`宣言でWebAssemblyをロードできるようにする[提案](https://github.com/WebAssembly/esm-integration)も行われるなど，相互連携はより容易かつ密になっていくと思われます．

# WebAssemblyの実行方式と表現

"Assembly"の名がついているものの，WebAssemblyはCPU上の機械語として実行されるわけではありません．WebAssemblyの実行環境はスタックベースの仮想マシンであり，ブラウザ上で実行されます．JavaScriptとは異なり，数値型として32bit/64bitの整数/浮動小数点型，また，ベクトル命令を意識した128bitベクトル型などが定義されています[^2]．逆に言うと，文字列型などはありません（このあたりはCPUっぽいです）．

アセンブリ言語=機械語の関係と同様，人間が読みやすい形式（[WebAssembly Text Format](https://developer.mozilla.org/ja/docs/WebAssembly/Understanding_the_text_format); wat）が用意されています．例えばC言語で書かれた関数
```c
double add(double x, double y) {
  return x + y;
}
```
をWebAssemblyに翻訳[^3]した結果は
```
(func $add (type 0) (param f64 f64) (result f64)
  (f64.add
    (local.get 0)
    (local.get 1)))
```
という"読みやすい"形で表現されます[^4]．

しかし，アセンブリ言語を直接記述することが滅多にないのと同様，多くのケースでは高級言語からWebAssemblyへのコンパイラを利用することになるでしょう．WebAssemblyへのコンパイルができる言語として，C/C++やRustなどのネイティブコンパイル系言語がよく紹介されますが，[その他様々な言語でのサポートも進んでいます](https://webassembly.org/getting-started/developers-guide/)．


# デモ

この節ではC++で作ったWebAssemblyアプリの実例を紹介します（ソースコードは[こちら](https://github.com/mrcdr/web-assembly-three-body)）．題材は古典力学（天体）の数値シミュレーションです[^5]．この題材を選んだ理由は

- そこそこヘビーな数値計算が必要なこと
- 最近筆者が中国発の某SF小説を読んだこと

です．C++ → WebAssemblyのコンパイラとしては[Emscripten](https://emscripten.org/)を使いました．
デモは[こちら](https://mrcdr.github.io/web-assembly-three-body/)からご覧ください（マウスでグリグリできます）．


WebAssembly/Emscriptenのすごいところは，このアプリを作るために**一行もJavaScriptを書いていない**ということです．書いたC++のソースコードはネイティブのアプリと全く同じようにmain関数から始まっています．さらにすごいことに，**同じソースコードをLinuxアプリケーションとしてもコンパイル・実行できます**：

![ss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631275/cea839fa-7fb0-67fe-20dd-f0b16a573671.png)

単に高速であるだけでなく，既存のネイティブアプリのコードを高い互換性でWebAssemblyにコンパイルできる環境が精力的に開発されていることも特筆すべき点だと思います．

# 私見 ― WebAssemblyに期待すること
Web系の技術は栄枯盛衰が激しいことから，どんな技術が今後流行るかは予測が難しいです．しかし，今やブラウザ上でオフィスソフトが動いたりゲームが遊べたりするなど，ブラウザサイドの体験がよりリッチな方向へ進化するという点はほぼ確実であると考えられます．

個人的に期待している応用は以下の二点です：

- 数値解析を多用する分野；機械学習，統計分析，シミュレーションなど
- ネイティブアプリのウェブ化（CADアプリケーションなど）

特に前者については，C++やFortranのような高速な言語で数値計算を実装し，インターフェースをPythonなどの軽量な言語で公開するライブラリ・ツールが数多く存在していることを鑑みると，そのウェブ版類似物がもっと登場しても良い気がします[^6]．Web系エンジニアの新しい選択肢としてはもちろん，より科学・工学領域に近いソフトウェアを書いているエンジニアにとっても，WebAssemblyは新たなソリューションを生み出す基盤になっていくと期待しています．


[^1]:ここに至るには[紆余曲折の歴史があった](https://zenn.dev/hodagi/articles/4925afbeb3c4dc)ようです
[^2]:[WebAssembly Specification](https://webassembly.github.io/gc/core/syntax/types.html)
[^3]:Clangと[WABT](https://github.com/WebAssembly/wabt)があれば次のコマンドで翻訳できます：`clang add.c -c -target wasm32 -O2 -o - | wasm2wat -`
[^4]:Text Formatの表現はS式と呼ばれておりLispの文法としても知られています（~~Lisp星人にとって読みやすいの間違いなのでは...~~）．いずれにしてもC言語，Lisp，機械語がWebの世界で一堂に会する点は技術的ロマンにあふれていると思います

[^5]:[ピタゴラス三体問題](https://ja.wikipedia.org/wiki/%E3%83%94%E3%82%BF%E3%82%B4%E3%83%A9%E3%82%B9%E4%B8%89%E4%BD%93%E5%95%8F%E9%A1%8C)
[^6]:実例として，Tensor FlowをJavaScript環境に移植した[TensorFlow.js](https://www.tensorflow.org/js?hl=ja)がWebAssemblyを用いて開発されています