コードキャッシュの改善
V8は、頻繁に使用されるスクリプトのために生成されたコードをキャッシュするためにコードキャッシングを使用します。Chrome 66から、トップレベルの実行後にキャッシュを作成することで、より多くのコードをキャッシュしています。これにより、初回読み込み時の解析時間とコンパイル時間が20〜40%削減されます。
V8は、頻繁に使用されるスクリプトのために生成されたコードをキャッシュするためにコードキャッシングを使用します。Chrome 66から、トップレベルの実行後にキャッシュを作成することで、より多くのコードをキャッシュしています。これにより、初回読み込み時の解析時間とコンパイル時間が20〜40%削減されます。
6週間ごとに、私たちはリリースプロセスの一環としてV8の新しいブランチを作成します。各バージョンは、Chrome Betaのマイルストーン直前にV8のGitマスタから分岐されます。本日、新しいブランチV8バージョン6.6を発表できることを嬉しく思います。このバージョンは、数週間後にChrome 66 Stableと連携してリリースされるまでベータ版です。V8 v6.6には開発者に向けた多くの魅力的な機能が詰まっています。この投稿では、リリースに先立つ注目すべきハイライトのプレビューを提供します。
要約: Chrome 66から、V8がJavaScriptのソースコードをバックグラウンドスレッド上でコンパイルするようになり、典型的なウェブサイトでメインスレッドのコンパイル時間が5%から20%短縮されました。
バージョン41以降、ChromeはV8のStreamedSource
APIを通じてバックグラウンドスレッドでのJavaScriptソースファイルの解析をサポートしています。これは、Chromeがネットワークからファイルの最初のチャンクをダウンロードするとすぐに、V8がJavaScriptソースコードの解析を開始できるようにし、Chromeがネットワーク経由でファイルをストリームする間に並行して解析を継続することを可能にします。これにより、V8がJavaScriptの解析をほぼ完了している状態でファイルのダウンロードが終了するため、読み込み時間が大幅に改善される場合があります。
しかし、V8の元々のベースラインコンパイラの制限により、V8はまだメインスレッドに戻り、解析を最終化し、スクリプトのコードを実行するためのJITマシンコードにコンパイルする必要がありました。Ignition + TurboFanパイプラインへの移行により、バイトコードコンパイルをバックグラウンドスレッドに移動することが可能になり、これによりChromeのメインスレッドが解放され、よりスムーズで反応の良いウェブブラウジング体験が提供されるようになりました。
V8のIgnitionバイトコードコンパイラは、パーサーによって生成された抽象構文木(AST)を入力として受け取り、JavaScriptソースを実行するための関連メタデータとともにバイトコード(BytecodeArray
)のストリームを生成します。
Ignitionのバイトコードコンパイラは、マルチスレッドを念頭に置いて構築されていますが、バックグラウンドコンパイルを可能にするためにはコンパイルパイプライン全体でいくつかの変更が必要でした。主な変更の1つとして、バックグラウンドスレッドで実行中のコンパイルパイプラインがV8のJavaScriptヒープ内のオブジェクトにアクセスすることを防ぐ必要がありました。JavaScriptがシングルスレッドであるため、V8のヒープ内のオブジェクトはスレッドセーフではなく、バックグラウンドコンパイル中にメインスレッドやV8のガーベッジコレクターによって変更される可能性があります。
コンパイルパイプラインには、V8のヒープ上のオブジェクトにアクセスする主な段階が2つありました: AST内部化とバイトコード最終化です。AST内部化は、ASTで識別されたリテラルオブジェクト(文字列、数字、オブジェクトリテラルなど)をV8ヒープに割り当てるプロセスであり、スクリプトが実行されるときに生成されたバイトコードによって直接使用できるようにします。このプロセスは従来、パーサーがASTを生成した直後に行われていました。そのため、コンパイルパイプラインの後続のステップでは、リテラルオブジェクトが割り当てられていることを前提としていました。バックグラウンドコンパイルを可能にするために、AST内部化をコンパイルパイプラインの後の段階、バイトコードがコンパイルされた後に移動しました。これにより、パイプラインの後続の段階で、ヒープ上で内部化された値ではなく、ASTに埋め込まれた_raw_リテラル値にアクセスするよう変更が必要でした。
バイトコード最終化は、関連するメタデータ(例: バイトコードが参照する定数を格納するConstantPoolArray
や、JavaScriptソースの行番号と列番号をバイトコードのオフセットにマッピングするSourcePositionTable
)とともに関数を実行するために使用される最終的なBytecodeArray
オブジェクトを構築するプロセスです。JavaScriptが動的な言語であるため、これらのオブジェクトはすべてJavaScriptヒープ内に存在し、バイトコードが関連付けられたJavaScript関数が収集される場合にガーベッジコレクションが可能である必要があります。従来、これらのメタデータオブジェクトのいくつかはバイトコードコンパイル中に割り当てられ、変更されるプロセスが含まれており、これにはJavaScriptヒープへのアクセスが必要でした。バックグラウンドコンパイルを可能にするために、Ignitionのバイトコードジェネレーターはこれらのメタデータの詳細を追跡し、それらを完全なコンパイルプロセスの最終段階までJavaScriptヒープ上に割り当てることを遅らせるようにリファクタリングされました。
これらの変更により、ほとんどすべてのスクリプトのコンパイルをバックグラウンドスレッドに移動することが可能となり、メインスレッドで実行されるのは短いAST内部化のステップとバイトコード最終化ステップのみとなり、それはスクリプト実行の直前に行われます。
現在のところ、トップレベルのスクリプトコードと即時呼び出し関数式(IIFE)のみがバックグラウンドスレッドでコンパイルされます。内部関数は依然として(最初に実行されたときに)メインスレッドで遅延コンパイルされます。将来的には、バックグラウンドコンパイルをより多くの状況に拡張することを目指しています。しかし、これらの制限がある場合でも、バックグラウンドコンパイルはメインスレッドをより長く自由にし、ユーザーインタラクションへの反応、アニメーションのレンダリング、またはそれ以外の場合でもスムーズで応答性の高い体験を提供するための作業を可能にします。
人気のあるウェブページのセットを対象にした私たちの実世界ベンチマークフレームワークを使用して、バックグラウンドコンパイルのパフォーマンスを評価しました。
バックグラウンドスレッドでコンパイルできる対象は、トップレベルのストリーミングスクリプトコンパイル中にコンパイルされたバイトコードの割合と、呼び出された内部関数として遅延コンパイルされる割合(メインスレッドで実行する必要がある部分)によって異なります。そのため、メインスレッドで節約される時間の割合も異なり、多くのページではメインスレッドのコンパイル時間が5%から20%の範囲で削減されます。
バックグラウンドスレッドでスクリプトをコンパイルするより良い方法は何でしょうか?スクリプトをまったくコンパイルする必要がないことです!バックグラウンドコンパイルと並行して、V8のコードキャッシングシステムを改良し、V8によってキャッシュされるコードの量を拡大することで、頻繁に訪問するサイトのページ読み込みを高速化する作業も行っています。この分野の進捗については、近々お知らせできることを期待しています。お楽しみに!
Chrome 66では、メモリリークのデバッグが格段に簡単になりました。ChromeのDevToolsは、JavaScriptから参照可能なすべてのC++ DOMオブジェクトをトレースおよびスナップショットを取得して、その参照とともに表示することができます。この機能は、V8ガベージコレクタの新しいC++トレースメカニズムの恩恵の一つです。
要約: 遅延デシリアライズが最近V8 v6.4でデフォルトで有効化され、V8のメモリ消費を平均でブラウザタブあたり500 KB以上削減しました。詳しくは以下をご覧ください!
まずは一歩下がって、V8が新しいIsolate(大まかに言えばChromeのブラウザタブに対応)を作成する際にどのようにヒープスナップショットを使用して速度を向上させているのか見てみましょう。私の同僚のYang Guoがカスタムスタートアップスナップショットの記事でこの点に関する優れた解説をしています:
6週間ごとに、リリースプロセスの一環としてV8の新しいブランチを作成しています。各バージョンは、Chrome Betaマイルストーンの直前にV8のGitマスターからブランチされます。本日、最新のブランチ、V8バージョン6.5を発表します。このバージョンは数週間後のChrome 65安定版と連携してリリースされるまでベータ版です。V8 v6.5は、開発者向けのさまざまな新機能を備えています。この投稿では、リリースを控えた注目のハイライトをいくつか紹介します。
Speedometer 1.0が2014年にリリースされて以来、BlinkとV8チームはこのベンチマークを人気のJavaScriptフレームワークの実際の使用状況の代理として活用し、ベンチマーク上で大幅な性能向上を達成しました。これらの改善が実際のユーザーに利益をもたらしていることを確認するため、実際のウェブサイトを測定したところ、人気のウェブサイトのページロード時間が改善されることでSpeedometerスコアも向上することを観察しました。
毎回6週間ごとに、私たちは リリースプロセス の一環として V8 の新しいブランチを作成します。各バージョンは Chrome Beta マイルストーン直前に V8 の Git マスターからブランチ化されます。本日、新しいブランチ V8 バージョン 6.4 を発表します。このバージョンは数週間後に Chrome 64 Stable と連携してリリースされるまでベータ版として利用可能です。V8 v6.4 には開発者向けの多くの機能が満載です。この投稿では、リリースに向けて注目すべき主な点をプレビューします。
コードカバレッジは、アプリケーションの特定部分が実行されたかどうか、必要に応じてどれくらい頻繁に実行されたかについての情報を提供します。テストスイートが特定のコードベースをどれほど徹底的に試験しているかを判断するために一般的に使用されます。
JavaScript開発者として、コードカバレッジが有効な状況に直面することがよくあります。例えば以下のような場合です:
console.log
を用いたprintf
\式デバッグやコードを手動でステップ実行する代わりに、コードカバレッジはアプリケーションのどの部分が実行されたかについてライブ情報を表示できます。