WasmGC と Wasm テール呼び出しの最適化がベースラインで新たに利用可能に

公開日: 2025 年 1 月 29 日

WebAssembly ガベージ コレクション(WasmGC)

プログラミング言語には、ガベージ コレクションを使用するプログラミング言語と、手動のメモリ管理が必要なプログラミング言語の 2 種類があります。前者の例としては、Kotlin、PHP、Java などがあります。後者の例としては、C、C++、Rust などがあります。一般に、高水準プログラミング言語には、ガベージ コレクションが標準機能として含まれています。

簡単に説明すると、ガベージ コレクションとは、プログラムによって割り当てられたが、参照されなくなったメモリの再利用を試みることです。このようなメモリはガベージと呼ばれます。ガベージ コレクションを実装する方法は多数あります。最も理解しやすい方法の 1 つは参照カウントです。これは、メモリ内のオブジェクトへの参照数をカウントすることを目的としています。

プログラミング言語は他のプログラミング言語で実装されているため、これはインセプションのように思えます。たとえば、PHP ランタイムは主に C で実装されています。デベロッパーが PHP などの言語を Wasm にコンパイルする場合、通常は、言語のパーサー、ライブラリ サポート、ガベージ コレクションなどの重要なコンポーネントなど、すべての部分をコンパイルする必要があります。

Wasm は、ホスト言語 JavaScript のコンテキストでブラウザ内で実行されます。Chrome では、JavaScript と Wasm は Google のオープンソース JavaScript エンジンである V8 で実行されます。また、V8 にはすでにガベージ コレクタがあります。つまり、Wasm にコンパイルされた PHP などを使用するデベロッパーは、ポートされた言語(PHP)のガベージ コレクタ実装を、すでにガベージ コレクタが存在するブラウザに配布することになります。これは、言うまでもなく無駄です。そこで役立つのが WasmGC です。

WasmGC について詳しくは、WebAssembly ガベージ コレクション(WasmGC)が Chrome でデフォルトで有効になりましたをご覧ください。さらに詳しくは、V8 のブログ投稿「ガベージ コレクションされたプログラミング言語を WebAssembly に効率的に移植する新しい方法」をご覧ください。

Wasm テール呼び出しの最適化

現在の関数から戻る前に実行される最後の命令である呼び出しは、テール位置にあると言われます。コンパイラは、呼び出し元のフレームを破棄し、呼び出しをジャンプで置き換えることで、このような呼び出しを最適化できます。これは、再帰関数で特に役立ちます。たとえば、リンクリストの要素の合計を計算する C 関数は次のようになります。

int sum(List* list, int acc) {
  if (list == nullptr) return acc;
  return sum(list->next, acc + list->val);
}

通常の呼び出しでは、O(n) のスタック空間が消費されます。リストの各要素が呼び出しスタックに新しいフレームを追加するためです。リストが長すぎると、すぐにスタックがオーバーフローする可能性があります。呼び出しをジャンプに置き換えることで、テール コールの最適化により、この再帰関数は O(1) スタック空間を使用するループに効果的に変わります。

int sum(List* list, int acc) {
  while (list != nullptr) {
    acc = acc + list->val;
    list = list->next;
  }
  return acc;
}

この最適化は、関数型言語では特に重要です。再帰関数に大きく依存しており、Haskell などの純粋な関数ではループ制御構造も提供されていません。通常、あらゆる種類のカスタム反復処理では、なんらかの方法で再帰が使用されます。テール呼び出しの最適化がないと、単純でないプログラムではすぐにスタック オーバーフローが発生し、スタック空間がすぐに不足します。

当初、WebAssembly ではこのようなテール呼び出しの最適化は許可されていませんでしたが、テール呼び出し拡張プロポーザルにより変更されました。詳しくは、V8 ブログの WebAssembly テールコールの記事をご覧ください。

まとめ

WasmGC とテール呼び出しの最適化がベースラインとして新たに利用可能になったことで、より多くのアプリでこれらの機能を使用してパフォーマンスを向上させることができます。たとえば、Google スプレッドシートは Google スプレッドシートの計算ワーカーを WasmGC に移植することで、パフォーマンスを向上させています。