統合ターミナルのパフォーマンス改善
2017年10月3日 Daniel Imms, @Tyriar
統合ターミナルのレンダリングエンジンは、Visual Studio Codeの次期バージョン1.17に向けて、パフォーマンスを念頭に置いて完全に書き換えられました。このバージョンでは、DOMベースのレンダリングシステムから、HTMLのキャンバス要素を使用するシステムに移行します。
DOMレンダリング
驚くべきことですが、静的なドキュメント表示用に設計されたシステムで、インタラクティブなターミナルをレンダリングすることが可能でした。しかし、時間が経つにつれて、いくつかの問題を解決するために、DOMが提供する特定の機能をオーバーライドする必要があることがわかりました
選択: ターミナルのユースケースをカバーするために、DOMの選択システムに逆らって多くの作業が行われました。DOMに表示されるものだけを常にレンダリングしていたため、選択を再実装せずに複数ページのコンテンツを選択することはできませんでした。スクロールすると選択が解除されることもありました。これらの問題を解決するために、カスタムの選択ロジックが追加されました。
文字のずれ: 多くの等幅フォントが一部のUnicode文字に対して厳密に等幅ではないため、下の画像の右側のような状況が発生することがありました。
この問題を回避する方法として、すべてのUnicode文字を固定幅のスパンで囲むというものがありましたが、これではフレームのレンダリングにかかる時間が増加します。
過剰なガベージコレクション: ターミナルをレンダリングするために必要な要素の数が多いため、ガベージコレクタは頻繁にメモリをクリーンアップする必要があり、レンダリング時間を著しく遅らせることがよくありました。この問題を回避するためにオブジェクトプールが導入され、DOM要素を再利用できるようになりました。
パフォーマンス: これらの問題を解決するためにどれだけ努力しても、レイアウトエンジンによって課されるハードキャップによってパフォーマンスは常に制限されます。
レイアウトエンジンの迂回
場合によっては、要素を構成してレイアウトを行うだけで1フレーム(16.6ms)よりも時間がかかることがあり、ターミナルでスムーズな60フレーム/秒(FPS)を維持したい場合、これは許容できません。この解決策は、新しいキャンバスベースのレンダリングエンジンでした。
<canvas>
HTML要素を使用すると、JavaScript APIを使用してグラフィックとテキストを描画できます。
レンダリングレイヤー
「レンダリングレイヤー」と呼ばれる複数のキャンバス要素を使用して、ターミナルの異なる部分のレンダリングを簡素化します。
現在のレイヤーは、以下の順序です。
- テキスト: 背景色と前景テキスト。このレイヤーは不透明です。
- 選択: マウスによる選択。
- リンク: リンクにカーソルを合わせたときのアンダーライン。
- カーソル: ターミナルのカーソル。
これらの部分を独自の小さなコンポーネントに分離することで、描画方法が大幅に簡素化されました。
変更された部分のみを描画
新しいレンダラーの重要な部分は、**変更された**ものだけを描画することです。そのため、セルの描画状態に関する最小限の情報を含むスリムな内部モデルが保持されています。この状態は、高価な描画アクションが実行される前に、セルが変更する必要があるかどうかをすばやく確認するために使用されます。**テキスト**レイヤーの場合、このモデルには文字、テキストスタイル、前景の色、背景の色への参照が含まれています。
これは、何も変更されていない場合でも、行全体がDOMから削除され、再構築され、再追加されていた以前のレンダリングエンジンとは対照的です。
上の画像の緑色の長方形は、再描画された領域を示しています。
テクスチャアトラス
テクスチャアトラスは、レンダリング時間をさらに高速化するために使用されます。舞台裏には、デフォルトの背景色で最も一般的なスタイルで、すべてのASCII文字を含むImageBitmap
があります。
これらのスタイルのテキストを描画する場合、CanvasRenderingContext2D.fillText
への通常の呼び出しの代わりに、テクスチャアトラスが使用されます。ImageBitmap
はGPU上に配置されているため、描画速度が大幅に向上します。
強制フレームスキップ
DOMでのレンダリング速度のため、パーサーが十分なCPU時間を確保できるよう、余分なフレームをスキップする必要がありました。これによりコマンドは以前よりも高速に実行できましたが、ターミナルを通じて大量のデータがストリームされると、フレームレートが10 FPSを下回る原因となりました。
新しいレンダラーでは、この制限が解除され、ターミナルで最大60 FPSを楽しむことができるようになりました。
結果
当社のベンチマークでは、統合ターミナルが状況に応じて**以前よりも約5〜45倍高速にレンダリングされる**ことが測定されました。応答性とフレームレートの向上に気づかなくても、レンダリングが高速化することでバッテリーの使用量も減ります!皆様がパフォーマンスの向上を享受されることを願っています。これらは数日中にVS Codeバージョン1.17に搭載され、現在Insidersビルドでテスト可能です。
さらに詳しく知りたい場合は、この機能を追加したオリジナルのxterm.jsプルリクエストもご覧ください。
ハッピーコーディング!
Daniel Imms、VS Codeチームメンバー @Tyriar