主要ブラウザでサポートされつつある WasmGC とは何なのか
※この記事は Cybozu Frontend Advent Calendar 2023 の 14 日目の記事です。
WasmGC とは
WasmGC(WebAssembly Garbage Collection)は、高級言語をより効果的に Wasm(WebAssembly) として利用するための機能として WebAssembly Community Group によって提案されました。
現状、WasmGC は Chrome 119、Firefox 120 や Edge 119 からデフォルトで有効化されており、Safari においても開発が進んでいます。
主に Kotlin や Dart/Flutter といった VM にガベージコレクタを含む言語を Wasm へ移植する際にこの機能の恩恵を受けることができます。
例えば、Kotlin で Web アプリケーション向けにプログラムを作成しブラウザ向けにコンパイルした場合、最新のベータ版では WasmGC を使用した Kotlin/Wasm
によるコンパイルが実行され、以前と同様のプログラムでも WasmGC が適用されたバイナリを生成することができます。
Wasm MVP の課題と課題の解消
従来の Wasm の仕様は WebAssembly MVP(Minimal Viable Product)と呼ばれ、必要最低限の機能のみがリリースされていました。
Wasm MVP には高級言語を移植する際、いくつかの課題が存在していました。
- ファイルサイズの肥大化
- 非効率なプロファイリングやメモリリーク
これらの課題は、WasmGC によって解決することができます。
ファイルサイズの肥大化
Wasm MVP では、ガベージコレクションを言語機能に含むような高級言語を Wasm へコンパイルする際、それらの機能もソースコードと同様に移植する必要がありました。
Wasm が動作する、V8 や Node.js といった VM の多くには既にガベージコレクタが組み込まれており、実質的にこれは余分な追加リソースといえます。
WasmGC では、Wasm 側の VM が持つガベージコレクタを移植元言語のガベージコレクタとして利用できるため、リソースを軽減することができます。
非効率なプロファイリングやメモリリーク
Wasm と JavaScript は相互にデータをやり取りする際、Wasm Table を用いてデータの参照を行います。
この手法では、JavaScript オブジェクトと Wasm 間での双方向リンクを持つことができず、VM 側のガベージコレクタは十分にデータのプロファイリングを実施することができません。
また、高級言語に実装されているガベージコレクタは Wasm が提供するリニアメモリ空間と相性が悪いため、長時間アプリケーションを動作させることによって断片化等によるメモリリークを引き起こす可能性があります。
WasmGC では、Wasm Table による値の参照ではなく、構造体や配列型を移植元言語に提供することによって移植元言語の値を VM が制御できるようになります。
これによって組み込みガベージコレクタが JavaScript オブジェクトと移植元言語の値を効率的にプロファイリングできるようになります。
また、ノンリニアメモリへのメモリ割り当てがサポートされるため、メモリリークの危険性も軽減されます。
WasmGC を使うには
ユーザとして WasmGC 利用したい場合、ターゲットとなる言語が WasmGC に対応している必要があります。
ターゲットとなる言語が既に WasmGC に対応している場合、ユーザは対応以前と同様のプログラムでその恩恵を受けることができます。
言語開発者は、WasmGC を導入するために移植元言語の型を WasmGC が提供する構造体やヒープ型といった型へキャストするようにコンパイラやビルドプロセスを実装する必要があります。
ユーザはこの仕様に触れなくとも恩恵を受けられますが、興味がある場合は WasmGC が提供する型を参照すると良いでしょう。
現状では Kotlin や Dart/Flutter がプレビュー版やアルファ版として WasmGC に対応しており、ユーザは追加のコストなく Web アプリケーションを構築できます。
WasmGC を利用したデモやソースコードも公開されているため、使ってみたい場合は後述のリンクを参照してください。
Kotlin Demo:
Kotlin Demo Source:
Dart/Flutter Demo:
Discussion