Asyncify
Asyncify は、同期CまたはC++コードと非同期JavaScriptの連携を可能にします。技術的には、JavaScriptに制御を戻す前にCのコールスタック全体を保存し、非同期呼び出しが終了した時点でそれを復元します。これはスタックスイッチングと呼ばれます。
WebAssembly PHP ビルドのネットワークサポートは Asyncify を使用して実装されています。PHP がネットワークリクエストを行うと、制御は JavaScript に返され、JavaScript がリクエストを行い、レスポンスの準備が整うと PHP が再開されます。この仕組みは十分に機能しており、PHP ビルドは Web API のリクエスト、Composer パッケージのインストール、さらにはMySQL サーバーへの接続も実行できます。
Asyncify クラッシュ
スタック切り替えには、非同期呼び出しを行う際にコールスタックに存在する可能性のあるすべてのC関数をラップする必要があります。すべてのC関数を一括ラップすると重大なオーバーヘッドが発生します。そのため、具体的な関数名のリストを保持しています。
残念ながら、このリストに1つでも項目が欠けていると、非同期呼び出し時にその関数がコールスタックの一部になっていると、WebAssembly がクラッシュします。これは次のようになります。

Asyncify は ASYNCIFY_ONLY なしでビルドした場合、必要な C 関数をすべて自動リスト化できますが、この自動検出は過剰であり、最終的に約 70,000 個の C 関数がリスト化され、起動時間が 4.5 秒にまで増加します。そのため、リストは手動で管理しています。
詳細にご興味がおありの場合は、GitHub の問題 251 を参照してください。
Asyncify のクラッシュを修正
Pull Request 253 は、特殊なテスト スイートを実行し、不足していることが判明した C 関数を ASYNCIFY_ONLY リストに自動的に追加する fix-asyncify コマンドを追加します。
上記のようなクラッシュが発生した場合は、次の方法で修正できます。
- クラッシュの原因となる PHP コードパスを特定します。ターミナルのスタックトレースが役立つはずです。
- クラッシュを引き起こすテストケースを
packages/php-wasm/node/src/test/php-asyncify.spec.tsに追加します。 npm run fix-asyncifyを実行します。- テストケース、更新された Dockerfile、再構築された PHP.wasm をコミットします。
今後の JSPI API では Asyncify は不要になります
最終的には、V8 がスタック切り替えを自動で処理し、この問題は完全に解消されるでしょう。Issue 134 では、その取り組みの進捗状況を追跡しています。
@fgmccabe からの 関連メモ は次のとおりです。
V8 の現在の実装は、実質的に「実験段階」です。arm64 と x64 の実装があります。 次のステップは、32 ビット ARM/Intel への実装です。そのためには、これまで解決する必要のなかったいくつかの問題を解決する必要があります。 Node.js については、おそらくフラグの背後で既に Node.js に組み込まれているでしょう。 フラグの要件を削除するには、他の実装が必要になります。その時期は今年末頃になる見込みですが、もちろんリソースと資金次第です。 さらに、標準化の取り組みをさらに進める必要がありますが、「小規模」な仕様であることを考えると、長期的な負担にはならないはずです。 これがロードマップの理解に役立つことを願っています :)