2022年10月12日発売予定の『O'Reilly Japan - ハンズオンWebAssembly』をMicrosoft MVPの北原 憲様に頂いたので、本の紹介と感想を述べていこうと思います。 普段本を全くというほど読まない私でありますが、日本語でWebAssemblyについて体系的に学べるものを探していたので読んでみました。
以後、『ハンズオンWebAssembly』を本書と呼称します。
はじめに
書評に移る前にどういった知識を持った人が読んだか、というのがあった方がこういう目線で見た場合、というのがわかりやすいと思うので、私のWebAssemblyに関する知識などのスペックを紹介します。
私は本書を読む以前からemscriptenを用いて、GitHubなどで公開されているCライブラリなどをwasmビルドし、JavaScriptなどで使用したり、emscriptenを内部的に使用しているBlazor WebAssemblyなどについてのある程度の知識を持っています。 そのためconfigureやGNU Makeなどを使ったプロジェクトであってもemscriptenを使用しビルドが行うことが出来ます。 しかし、WebAssembly自体の知識は乏しく、ブラウザなどの環境でCライブラリが動かせる物、程度の理解度であるとお考えください。
その私が、WebAssemblyを使ったアプリケーションを作る上で、バンドルサイズの肥大化や、機械学習ライブラリと組み合わせた場合の高速化など、そのヒントがないかという観点から本書を読んだ感想となります。
もくじと概要、感想
1章 WebAssemblyとの邂逅
WebAssemblyという技術を取り巻く歴史から、実際にコンパイルされて動作するまでの仕組みについて解説している。 さらにWebAssemblyがもたらすパフォーマンスの改善効果やメリットについて触れている。
WebAssemblyが本書で取り上げられていないどんなフレームワークや現場で活用されているかについても書かれていて、事例を知る上でも非常に参考になった。
2章 WebAssemblyモジュールの基礎
WebAssemblyモジュールのバイナリのバイトコードが、どの様なセクションに分けられていて、どの様な役割を果たしているかの解説をしている。
多くの場合、この内部の配置について知る必要は無いように思うが、11章のテキスト形式のWebAssemblyを学ぶ上で重要になる知識であるので、何度も読み返した章の一つ。 例えばビルド時にシンボルが出力されていないが、何を見て調べればよいかなどの時に、このセクションの話などが役に立つ時が来ると思っている。
3章 WebAssemblyモジュール開発の第一歩
emscriptenを使用して素数を計算参するCモジュールをビルドし、JavaScript上で動作させるまでの流れを解説している。 emscriptenにはC, C++ファイルをwasmにビルドし、それを動作させるためのHTMLやJavaScriptバインディングを出力する機能があるが、それを使ったものや、それを使わずにWebAssembly JavaScript APIを使用してインスタンス化し使用する例の双方を解説している。
自分はWebAssembly JavaScript APIを使用したインスタンス化しか触れてこなかったため、こんなにも簡単にWebAssemblyに触れることが出来るのかと驚いた。 ぜひともこの章を見て、実際に自分の手で試してほしい。
4章 既存のC++コードの再利用
商品管理アプリケーションの検証ロジックを例に、検証ロジックを実装したC++ファイルをemscriptenでビルドし、JavaScriptアプリケーションで動作させる例を紹介している。 既存のコードに対して条件付きコンパイルシンボルを付与する方法でシンボルを残し、emscriptenのccallでバインディングする、今後の章でも使用するCバインディングの基礎を学ぶことが出来る。
単純なCライブラリを使用するのであれば、この章の知識があれば十分なほど詳しく解説されている。 後述するが、Cでの型に対応するパラメータは…といったことはこの場では解説されておらず、付録に対応する型が載っている。 ここで紹介されているのは、あくまでも今回題材としたアプリケーションを動作させるために必要なパラメータなどであることに注意してほしい。
5章 JavaScriptを呼び出すWebAssemblyモジュールの作成
4章ではJavaScriptからCの関数を呼び出しているが、本章ではCからJavaScriptを呼び出す方法について解説している。 emscriptenの作成するJavaScriptファイルに対して、ビルド時にCから呼び出す実装をマージする方法や、WebAssemblyモジュールのインスタンス化のタイミングで実装を渡す2種類の方法について解説している。
この章の知識は相互運用を行う上で非常によく使う内容だったため、読み応えがあった。
6章 関数ポインタを用いたWebAssemblyモジュールとJavaScriptのコードの連携
本章では関数ポインタを用いたWebAssemblyモジュールとJavaScriptコードの連携について解説している。 Validation関数の成功や失敗をcallbackという形で実装し、例えばPromiseオブジェクトでラップするといった応用例を載せている。
ここでは2章で触れたセクションの話も盛り込まれていて、理解するのに時間を要した章だった。 2章から5章までの集大成と言える章と言えるだろう。 今後関数ポインタを用いたコードや、またcallbackとして扱いたいケースが出てきた場合に参考になるコードがあったためぜひとも覚えておきたい章だと感じた。
7章 動的リンクの基礎
本章では動的リンクの長所や短所、また実現するための3つの方法をコードを交えて解説している。 呼び出し側のメインモジュールと呼び出される側となるサイドモジュールの関係性を図解している。 また書く方法のメリットやデメリット、制御をどのレイヤーで行いたいか簡潔にまとめている。
本書で私が最も興味を持っていた内容の基礎を解説してくれた章である。 複数のUsecaseを1つのwasmファイルにビルドすると、初期のダウンロードに時間がかかってしまい困っていたが、動的リンクの手法を取ることで解消が出来そうだと感じた。 その上で、複数ある動的リンクのメリットやデメリットについて簡潔にまとめてあるこの章は非常に学びの多いものだった。
8章 動的リンクの実装
7章で解説した手法一つである、emscripten のdynamicLibraries
配列を用いた手法で、SPAでページに応じたWebAssemblyモジュールを動的にリンクし使用する例について解説している。
これを実現するにあたって必要なemscriptenのビルドフラグの MODULARIZE
フラグについて詳細に解説している。
この章ではMODULARIZEフラグについて触れ、複数のModuleオブジェクトのインスタンスが作成出来ることについて触れいていたが、更にWebAssemblyモジュールのダウンロードやインスタンス化のタイミングの制御についても触れている、非常に実用的な内容だった。
9章 Web Workerとpthreadによるスレッド処理
WebブラウザのUIとJavaScriptは単一スレッドで実行されることについて触れ、メインスレッドをJavaScriptの制御で止めてしまう問題を解決する一つとしてWeb Workerが使われることを述べている。 本章ではWeb Workerを用いてWebAssemblyモジュールのプリフェッチとコンパイルを行い、メインスレッドにそのインスタンスを戻す方法と、Web Worker上で利用可能なpthreadを用いた並列処理について解説している。
自分が知りたかったWeb Workerについて取っ掛かりの知識を与えてくれた章である。 Web Workerを使えば例えば機械学習を用いたライブラリとの組み合わせにおいて、メインスレッドを停止させることなく処理を実現できるなというざっくりとした予想はしていたが、この章を読んでそれが実現できそうだということが見えた。 本書で触れられていないemscriptenのWorker APIについてのリンクが参考に載っていたため、それをもとに挑戦したいと感じた。 ブラウザやWeb Workerの制約について簡潔に述べられているため、WebAssemblyを使用しない場合においても、Web Workerの概要を知る上で非常に良い章だった。
10章 Node.jsでのWebAssemblyモジュールの活用
9章まではサンプルコードは全てブラウザ上で動作させていたが、本章ではNode.jsで動作させる例を解説している。 ブラウザ(クライアント)で使用していた検証ロジックをそのままの形でNode.js(サーバーサイド)で動作させることが可能ということをサンプルを交えて紹介している。
ブラウザでのWebAssemblyモジュールの読み出し方やEmscriptenでのモジュールの使い方について差分をわかりやすく解説しているため、9章までの内容が理解できていた場合すぐに試すことができそうな内容だった。 本書が執筆された時期も関係するが、Node.js v16などでESModules対応になり、またemscriptenでもESModules対応しているため、将来的に内容の乖離が起こるかもしれないと感じた。 しかし紹介されているベースの内容としては大筋変わらないため、サーバーサイドでWebAssemblyを使用したい場合は、この章を参考にするとよいだろう。
11章 WebAssemblyのテキスト形式
WebAssemblyはバイナリ形式とS式で記述されたWATと呼ばれるテキスト形式があり、そのWATについて実際にコードを書き、2章で解説していた各セクションとの対応付を行いながら解説している。 最終的にwatをwasmに変換し、ブラウザ上で動かす例を紹介している。
……正直なところ何度読み返してもまだ理解が追いついていない章である。 詳細なWebAssemblyモジュールの調査などに使えそう…とは思うのだが、こういうものがある、という風な認識に今は止めておこうと思った章である。
実際にMDNでテキスト形式について解説しているページを見ると
WebAssembly テキスト形式の理解 - WebAssembly | MDN
メモ: この記事は、あなたがウェブ開発者で wasm モジュールをページに読み込んでコード内で使用するだけなら過剰なものかもしれません (WebAssembly JavaScript API の使用を参照)。しかし、例えば、パフォーマンスを最適化するために wasm モジュールを書きたいときや、あなた自身で WebAssembly コンパイラーを作るときには役に立ちます。
非常に発展的な内容であることがわかる。必要となったタイミングでこの章を思い出し、活用できればと思う。
12章 デバッグ
本章では11章で触れたWAT形式WebAssemblyモジュールに変換し、実際に動作させながらデバッグする方法について解説している。 JavaScript側のエラーなどをChromeなどのブラウザのconsoleで確認し、その情報を元にDeveloperToolsなどを併用してデバッグしていく流れを追うことが出来る。
あえて誤ったコードを記述し、段階的に修正していく流れをトレースできるため、実際の開発にも役に立つデバッグ方法の一つだと感じた。 emscriptenを今回は使用しておらず、gフラグなどのデバッグ情報についての詳細は触れられていないため、自分で簡単なアプリケーションを用意し、試して理解を深めるのが良いと感じた。
13章 テストーーそして?
Mochaを使用したNode.jsでのテスト、またブラウザ上でのテストの実行の仕方を解説している。
実際に動作させて確認していくのもいいが、この章で扱っているようにテストを書くことで多くのメリットを享受することが出来る。 実際に自分もWebAssemblyを使ったアプリケーションに限らず多くのアプリケーション開発でテストを書いて、自動テストを回している。
おわりに
おすすめする人
性質上C, C++など、JavaScript以外の言語も触れたり、emscriptenを使う上でも他の言語ランタイムなどを入れる必要があるので初学者がいきなり立ち向かうのは難しいだろう。 しかし、一部をつまみ食いして、WebAssemblyモジュールを使うにはここに注意すれば良い、というエッセンスだけを得るだけでも十分なので、一定のJavaScriptなどの知識を持った、WebAssemblyを使用してアプリケーションを開発する人全般におすすめしたい。
この本を読む上で注意したいこと、また本書で扱っていないこと(と感じたこと)
初学者には少し難しそうだと感じたのは一点あるが、本書のタイトルの『EmscriptenとC++を使って学ぶ』のEmscriptenのところに反応し、Emscriptenの詳しい解説だったり、提供している各種API、モジュールについての説明が知りたい人には向かないだろう。 WebAssemblyを使用するためのツールキットとしてEmscriptenを本書では扱っているが、今回題材としたアプリケーションをビルドし動作させるための最低限のオプションだったり、APIの解説にとどめている。 関連情報としてリンクを載せているため、足がかりにはなるところもある。
また複雑な、例えばconfigureだったりCMake, GNU Makeなどを使用したアプリケーションをビルドするにはと言った方法論についても載っていない。
そういったミスマッチをあらかじめ除いて読むと、非常に良い学びが得られるだろう。
総評
WebAssemblyについての体系的な知識を手に入れたり、検索する上での単語のインデックスが欲しいのであればぜひとも読んでほしい一冊だった。 題材としているアプリケーションはシンプルなものでイメージもしやすく、自分で改造して試すことがしやすいのも評価のポイントだった。
このアプリケーションのサイズ感で、アプリケーションが大規模になってきた場合、どの様に立ち向かうかについて7章から動的リンクについて触れてカバーしたり、重い処理を行う場合の対処としてWeb Workerを採用することにも触れられているのは驚きである。 WebAssemblyを用いたアプリケーション開発のエッセンスを盛り込んだ一冊と言える。
あらためて、本を送って頂いた北原様と、著者ならびに訳者、出版社の方々に感謝します。