プログラミング
WasmtimeにおけるGCと例外
GC and Exceptions in Wasmtime (bytecodealliance.org)
要約
Wasmtime 47リリースにより、WebAssembly (Wasm) のガベージコレクション (GC) と例外処理の提案がデフォルトで有効になりました。これにより、高水準言語がWasmをより効率的にターゲットできるようになり、WasmtimeのGC実装とその利点、今後の開発についても詳述されています。
全文翻訳
今日のWasmtime 47リリースでは、Wasm GCと例外の提案が両方ともデフォルトで有効になりました!私たちは、より多くの言語をWebAssemblyおよびWasmtimeが実行されるあらゆる場所に持ち込むお手伝いができることを嬉しく思っています。この段階に到達するには、Wasmtimeの大きな変更が必要であり、長年のエンジニアリング努力の集大成を表しています。
Wasmtimeは、高速、安全、ポータブルなWebAssemblyランタイムです。スタンドアロンで、軽量で、組み込みが容易です。Wasmtimeのメンテナーはオープンスタンダードにコミットしており、Wasm標準化に積極的に参加しています。
Wasm GC
元々、WebAssemblyの最初のバージョンでは、オブジェクトと参照のデータモデルを持つ高水準言語(生のポインタとメモリのデータモデルとは対照的に)は、独自のガベージコレクタを.wasmバイナリ内に埋め込む必要がありました。これにより、.wasmバイナリが肥大化し、スタックマップやスタックウォークを使用してGCルートを特定するなど、コレクタをネイティブコードで実装する際にしばしば使用される多くのテクニックが利用できなくなりました。そして残念ながら、多くの言語がこのカテゴリに該当しました。
Wasm GC提案は状況を改善し、これらの高水準言語に対する効率的なサポートをWebAssemblyに追加します。1これはWebAssembly言語を拡張し、Wasmプログラムが独自の構造体と配列の型、およびサブタイピング関係を定義できるようにします。Wasmプログラムは、これらの型のインスタンスのライフタイムを管理したり、手動で解放したりすることを心配する必要はありません。ランタイムがそれらすべてを処理します。したがって、独自のガベージコレクタを埋め込む必要はなくなり、これらのツールチェーンは代わりにWebAssemblyランタイムのコレクタを利用できます。これにより、より多くの言語がWebAssemblyを容易かつ効率的にターゲットできるようになります。例として、Wasmプログラムがバイナリツリーのノード型を定義する方法を次に示します。
(rec (type $node (struct (field $key (mut f64)) (field $left (mut (ref null $node))) (field $right (mut (ref null $node))) (field $value (mut (ref null $payload))) )) )
新しいインスタンスはstruct.new $nodeで作成され、フィールドは例えばstruct.get $node $keyまたはstruct.set $node $left命令でアクセスされます。
Wasm例外
Wasmの例外提案は、オブジェクトと参照の言語に対するWasm GC提案の目標と同様の目標を例外を使用する言語に対して持っています。それは、WebAssemblyでの例外の効率的なサポートを可能にし、例外を持つ言語のより良いコンパイルターゲットにすることを目指しています。2この提案なしでは、ツールチェーンは関数結果だけでなく、関数が正常に返ったか例外をスローしたかを示す条件を返すカスタム呼び出し規約を実装する必要がありました。すべての呼び出しサイトはこの条件をテストし、適切に分岐する必要があり、.wasmバイナリの肥大化と、一般的な正常復帰パスの実行時オーバーヘッドの両方に追加されていました。しかし、例外提案により、それらすべてが消え、throwおよびtry/catchスタイルの構成に置き換えられます。WebAssemblyランタイムは、一般的な正常復帰呼び出しパスにゼロオーバーヘッドを課す従来のアンワインドアプローチでこれらを実装する自由を得て、実行速度の向上と.wasmバイナリの縮小につながります。
WasmtimeのGC実装
Wasmtimeは、シンプルなCheneyスタイルのセミスペースコピーコレクタを備えています。GCヒープは2つの半分に分割されています。「アクティブ」セミスペース(新しいオブジェクトが割り当てられる場所)と「アイドル」セミスペースです。収集中、ライブオブジェクトはアイドルスペース(以前のアクティブスペースだった場所)から新しいアクティブスペースにコピーされ、すべてのGCルート(例: Wasmスタックフレーム内のアクティブな参照)は新しい場所を指すように更新されます。割り当てはアクティブセミスペース内の単純なバンプポインタであり、コレクタは読み取りまたは書き込みバリアを必要としません。
私たちは、GCヒープを実装およびサンドボックス化するために、WebAssembly線形メモリを内部的に再利用しています。GCオブジェクトへの参照はネイティブポインタではなく、GCヒープの基盤となる線形メモリへの32ビットインデックスです。WebAssemblyは高速、安全、ポータブルであることを約束しますが、その責任を実際に担うのはランタイムの実装であり、GCヒープに線形メモリを再利用することは、これら3つのすべての側面で利点があります。おそらく最も明白なのは、防御的な安全性の意味合いです。GCヒープを破損させるコレクタのバグに直面した場合でも、悪意のあるWasmプログラムはサンドボックスをエスケープしてホストメモリにアクセスすることはできません。高速性に関しては、線形メモリで行っているように、仮想メモリガードページを使用して明示的な境界チェックを省略できます。ポーリングインスタンスアロケータとの緊密な統合により、5マイクロ秒のインスタンス化時間を維持できます。また、64ビットマシンでは、32ビットGC参照は64ビットポインタよりもコンパクトであり、CPUキャッシュをより効率的に利用できます。最後に、多くのプラットフォーム(ベアメタルを含む!)で、それぞれ微妙に異なる機能を持つ、大規模なメモリ領域の割り当て、解放、リセットを迅速に行うことは、多くの特別なケース処理を伴います。線形メモリの既存の実装は、すでにこれらのプラットフォーム全体でポータブルであり、すでにその特別なケース処理を行っているため、線形メモリの上にGCヒープを構築することにより、ポータブルなGCヒープも「無料で」入手できます。
コレクタの正確性に対する信頼をさらに高めるために、Wasm GCを徹底的にテストするために、ファジングインフラストラクチャを拡張しました。まず、GC提案をサポートするようにwasm-smithを拡張しました。理論的には、十分な時間があれば、GCを使用するほぼすべてのWasmプログラムを生成できます。3しかし、それは非常に時間がかかる可能性があるため、2つの追加のファザーで補完しました。
1つは、興味深く任意のオブジェクトグラフ、型参照、およびサブタイピング関係を実行するように設計されています。
もう1つは、コレクタのバグやコンパイラの誤最適化によるヒープ破損を検出するように設計されています。
最後に、パフォーマンスに関する簡単な注意点として、期待値を設定します。これまでのところ、エンジニアリングの労力はコレクタの正確性に主に焦点を当てており、パフォーマンスにはあまり焦点を当てていません。これは新品であり、例えばV8やSpiderMonkeyのコレクタとは異なり、数十年にわたるパフォーマンスエンジニアリングの恩恵を受けていません。私たちのコレクタのスループットとレイテンシは、今日ではそれらに匹敵しません。さらに、私たちは主に、Wasmtimeが本番環境で最も使用されるユースケース、つまり、少数のタスクを処理してから、そのGCヒープとともに破棄される、多くの小さな使い捨てWasmインスタンスを作成するというシナリオのために、コレクタとそのトレードオフを設計してきました。システムは、単一インスタンスのパフォーマンスを最優先するのではなく、まず多くのインスタンスに水平にスケーリングするように設計されています。このシナリオは、例えば、無期限の寿命を持つ単一の長寿命サーバープロセスとは異なります。それをチューニングするコレクタも異なるでしょう。
今後の予定
パフォーマンス作業はまだたくさん残っています。例えば、現在、コンパイラのエイリアス解析最適化(ストア・ツー・ロード転送や冗長ロード削除など)をGC型情報で拡張するプロセスを進めています。2つの型が決してエイリアスしない(つまり、同じメモリ位置を占有しない)ことがわかれば、これらの最適化をより積極的に行うことができます。
機能面での次の大きなマイルストーンは、遅延値低下の上にコンポーネントモデルとのGC統合をプロトタイプすることです。この取り組みは、ガベージコレクションされた言語がコンポーネントエコシステムでファーストクラスの市民になることを促進します。なぜなら、コンポーネント間でデータを渡すためだけに、これまで不要だった線形メモリを必要としなくなるからです。
結論
このマイルストーンに到達できたことを嬉しく思います!Wasmtimeの新たに有効になったGCと例外サポートをテスト実行し、結果をお知らせください。GC提案はメインのWebAssembly仕様にマージされたため、提案ページは特定の時点のスナップショットとしてアーカイブされました。↩
GC提案と同様に、例外提案もメインのWebAssembly仕様にマージされ、提案リポジトリは現在アーカイブされた歴史的なスナップショットです。↩
執筆時点でのwasm-smithのWasm GCに関する唯一の盲点は、それが生成しないということです。