V8にヘッズアップを与える: 明示的なコンパイルヒントでJavaScriptの起動を高速化
JavaScriptを高速で動作させることは、応答性の高いWebアプリケーションには欠かせません。V8の高度な最適化をもってしても、起動時に重要なJavaScriptを解析およびコンパイルすることがパフォーマンスにボトルネックをもたらす場合があります。初期スクリプトのコンパイル中にどのJavaScript関数をコンパイルするかを把握することで、Webページの読み込みを高速化できます。
JavaScriptを高速で動作させることは、応答性の高いWebアプリケーションには欠かせません。V8の高度な最適化をもってしても、起動時に重要なJavaScriptを解析およびコンパイルすることがパフォーマンスにボトルネックをもたらす場合があります。初期スクリプトのコンパイル中にどのJavaScript関数をコンパイルするかを把握することで、Webページの読み込みを高速化できます。
V8の最上位最適化コンパイラTurbofanは、Sea of Nodes (SoN)を使用する数少ない大規模プロダクションコンパイラの1つとして知られています。しかし、約3年前からSea of Nodesを廃止し、より伝統的な制御フローグラフ (CFG) 中間表現 (IR)に戻りました。それをTurboshaftと名付けました。現在では、TurbofanのJavaScriptバックエンド全体がTurboshaftを使用しており、WebAssemblyはその全パイプラインを通じてTurboshaftを使用しています。Turbofanの2つの部分ではまだSea of Nodesが一部使用されています。1つは組み込みパイプラインで、これをTurboshaftに置き換えつつあります。もう1つはJavaScriptパイプラインのフロントエンドで、これをMaglevという別のCFGベースのIRに置き換えています。このブログ記事では、Sea of Nodesを廃止することになった理由を説明します。
V8では、JavaScriptのパフォーマンス向上に常に努めています。この努力の一環として、最近JetStream2のベンチマークスイートを見直し、パフォーマンスの問題を解消しました。この投稿では、async-fs
ベンチマークで大幅な2.5倍
の改善を達成し、全体スコアに著しい向上をもたらした特定の最適化について詳しく説明します。この最適化はベンチマークから着想を得ましたが、実際のコードでも類似のパターンが見られます。
JavaScript Promise Integration (JSPI) APIは、外部機能への_同期的_なアクセスを想定して書かれたWebAssemblyアプリケーションが、実際には_非同期的_に動作する環境でスムーズに操作できるようにします。
WebAssemblyのJavaScript Promise Integration (JSPI) APIに新しいAPIが登場しました。これはChromeリリースM126で利用可能です。変更点、Emscriptenでの使用方法、JSPIのロードマップについて説明します。
JSPIは、逐次処理APIを使用したWebAssemblyアプリケーションが、非同期のWeb APIにアクセスするためのAPIです。多くのWeb APIはJavaScriptのPromise
オブジェクトを基に作成されています。つまり、要求された操作を即座に実行する代わりに、それを実行するPromise
を返します。一方で、WebAssemblyにコンパイルされた多くのアプリケーションは、呼び出し元が完了するまでブロックするAPIが主流のC/C++の世界から来ています。
約3年前の初期設計ドキュメントと、それまでの間に作成された数百のCLにより、V8のインプロセス・サンドボックス — V8の軽量なインプロセスサンドボックス — は実験的なセキュリティ機能とみなされなくなる段階に達しました。本日より、V8サンドボックスはChromeの脆弱性報奨プログラム (VRP) に含まれるようになりました。強力なセキュリティ境界を形成するにはまだいくつかの問題を解決する必要がありますが、VRPへの含有はその方向性への重要な一歩です。したがって、Chrome 123はある種の「ベータ」リリースと見なされるでしょう。このブログ記事では、サンドボックスの背景にある動機を説明し、それがV8内のメモリ破壊がホストプロセス全体に広がることをどのように防ぐかを示し、最終的に、なぜこれがメモリ安全性への必要不可欠なステップであるかを説明します。
WebAssemblyのJavaScriptプロミス統合(JSPI) APIがChromiumリリースM123でオリジントライアルに入ります。これにより、あなたやユーザーがこの新しいAPIから受けるメリットをテストできます。
JSPIは、WebAssemblyにコンパイルされたいわゆる逐次コードが_非同期_なWeb APIにアクセスできるようにするAPIです。多くのWeb APIはJavaScriptのPromise
を使用して作成されています。そのため、操作をすぐに実行する代わりに、操作を実行するためのPromise
を返します。操作が最終的に実行されると、ブラウザのタスクランナーがそのPromise
に関連付けられたコールバックを呼び出します。JSPIはこのアーキテクチャにフックして、WebAssemblyアプリケーションがPromise
を返した時点で一旦中断され、Promise
が解決された時点で再開できるようにします。
あなたはundefined
、true
、その他のコアJavaScriptオブジェクトがどこから来るのか考えたことがありますか?これらのオブジェクトは、任意のユーザー定義オブジェクトの基本単位であり、最初に存在している必要があります。V8はこれらを固定不変なルートと呼び、それらは専用のヒープ – 読み取り専用ヒープに住んでいます。これらは頻繁に使用されるため、迅速なアクセスが重要です。そしてコンパイル時にメモリアドレスを正しく予測するほど迅速な方法はないでしょうか?
速さが単なる特徴ではなく、生活の一部である刺激的なV8の世界へようこそ。2023年を締めくくるにあたり、今年達成したV8の印象的な成果を祝う時が来ました。
革新的なパフォーマンス最適化を通じて、V8はWebの進化し続ける景観において可能な限界を押し広げ続けています。今年は、新しい中間層コンパイラを導入し、上位層コンパイラのインフラストラクチャ、ランタイム、ガベージコレクタにいくつかの改善を実施しました。その結果、広範囲で大幅な速度向上が実現しました。
Chrome M117では、新しい最適化コンパイラMaglevを導入しました。Maglevは既存のSparkplugとTurboFanコンパイラの間に位置し、高速な最適化コンパイラとしての役割を果たし、十分に良いコードを十分に速く生成します。
2021年まで、V8には2つの主要な実行階層がありました。Ignition(インタープリタ)と、ピーク性能を重視したV8の最適化コンパイラTurboFanです。すべてのJavaScriptコードは最初にIgnitionのバイトコードにコンパイルされ、それをインタープリトして実行されます。実行中、V8はプログラムの挙動を追跡し、オブジェクトの形状や型を記録します。ランタイムの実行メタデータとバイトコードの両方が最適化コンパイラに供給され、高性能でしばしば推測的な機械コードが生成され、インタープリタよりもはるかに速く実行されます。