Quantcast
Channel: Google Developers Japan
Viewing all articles
Browse latest Browse all 2207

Windows 版 Chrome のパフォーマンス改善とネイティブ ウィンドウ オクルージョンの導入

$
0
0
この記事は Chrome デベロッパー、David Bienvenu による Chromium Blog の記事 "Chrome on Windows performance improvements and the journey of Native Window Occlusion" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。




ブラウザをタブグループで整理している方でも、ウィンドウに名前を付けている方でも、タブ検索やその他の方法を使っている方でも、目的のタブにたどり着くためにたくさんの機能を使うことができます。速さと好奇心の今回の投稿では、どのウィンドウが表示されているかを利用してどのように Chrome を最適化したかについて説明します。その結果、起動が 25.8% 速くなり、クラッシュは 4.5% 減少しました。

背景

Chrome では、数年間にわたるユーザー エクスペリエンス改善の取り組みの中で、バックグラウンド タブの優先度を下げてきました [1]。たとえばバックグラウンド タブでは、JavaScript の速度を制限したり、ウェブ コンテンツのレンダリングを抑制したりしています。これにより、CPU や GPU、メモリの使用量が減少し、実際にユーザーに表示されるフォアグラウンド タブで利用できるメモリや CPU、GPU が増加します。一方で、このロジックの対象になるのは、ウィンドウでフォーカスが当たっていないタブ、最小化されているウィンドウ、画面外のウィンドウのみです。

実験を通して、Chrome のウィンドウの 20% 近くが、完全に別のウィンドウのうしろに隠れている(オクルージョンされている)ことがわかりました。私たちは、こういったオクルージョンされているウィンドウをバックグラウンド タブと同じように扱うことができれば、パフォーマンスは大幅に向上するに違いないという仮説を立てました。そこで、今から 3 年ほど前に、各 Chrome ウィンドウのオクルージョン状態をリアルタイムに追跡し、オクルージョン対象のウィンドウのタブの優先度を下げるというプロジェクトを始めました。このプロジェクトを行うには、ユーザーの画面に表示されている Chrome 以外のウィンドウのネイティブ位置を知る必要があります。そこで、プロジェクトをネイティブ ウィンドウ オクルージョンと名付けました(位置情報は、オクルージョンの計算に使った後、即座に破棄しています)。

ネイティブ ウィンドウ オクルージョンの計算

Windows OS では、あるウィンドウが完全に他のウィンドウに隠れているかどうかを直接的に知る方法は提供されていません。そのため、Chrome は独自に検知する必要があります。他の Chrome ウィンドウだけを考えればよいのなら、これは簡単です。Chrome のウィンドウがどこにあるかはわかっているからです。しかしここでは、ユーザーが開いているかもしれない Chrome 以外のウィンドウをすべて考慮し、Chrome のウィンドウのオクルージョン状態が変わるかもしれないイベントをすべて検知する必要があります。

どの Chrome ウィンドウがオクルージョン対象かを継続的に追跡するには、主に 2 つのことが必要です。1 つ目はオクルージョンの計算です。ここでは、デスクトップで開いているウィンドウについて z-order順(前から後)に反復処理を行い、そのウィンドウが Chrome ウィンドウを完全に隠しているかどうかを確認します。2 つ目は、そのオクルージョンの計算をいつ行うかを決めることです。

オクルージョンの計算

理論的には、どのウィンドウがオクルージョン対象かを判断するのは簡単です。しかし実際には、マルチモニタ環境仮想デスクトップ透過ウィンドウクロークされたウィンドウなど、複雑な要素がたくさん存在します。この点には、慎重に対処しなければなりません。実際にユーザーに表示されているウィンドウをオクルージョン対象と判断してしまうと、ウェブ コンテンツが表示されるはずの場所が白くなってしまうからです。また、オクルージョンの計算をしている間に UI スレッドをブロックすることは、Chrome の応答性とユーザー エクスペリエンスが悪化する可能性があるため、避けなければなりません。そこで、次のようにして別のスレッドでオクルージョンの計算をしています。
  1. 最小化されたウィンドウは表示されないので、無視する。
  2. 別の仮想デスクトップ上にある Chrome ウィンドウはオクルージョン対象とマークする。
  3. ディスプレイのモニターを組み合わせた仮想画面の矩形を計算する。これがオクルージョンされていない画面の矩形になります。
  4. デスクトップで開いているウィンドウについて、前から後の順番に反復処理を行う。見えないウィンドウ、透明なウィンドウ、フローティング ウィンドウ(スタイルが WS_EX_TOOLBARであるウィンドウ)、クロークされたウィンドウ、他の仮想デスクトップのウィンドウ、非矩形ウィンドウ [2]などは無視する。重要な点として、このようなウィンドウを無視すると、オクルージョン対象のウィンドウの一部が表示されているものと見なされる(偽陰性)可能性がありますが、表示されているウィンドウがオクルージョン対象と見なされる(偽陽性)ことはありません。各ウィンドウについて以下を行います。
  • オクルージョンされていない画面の矩形から対象のウィンドウの領域を引く。
  • 対象のウィンドウが Chrome ウィンドウである場合は、その領域がオクルージョンされていない領域と重なっているかどうかを確認する。重なっていない場合、その Chrome ウィンドウは前にあるウィンドウによって完全に覆われているため、オクルージョン対象になります。
  • すべての Chrome ウィンドウの計算が終わるまで繰り返す。
  • この時点で、オクルージョン対象とマークされていない Chrome ウィンドウは表示されていることになり、オクルージョンの計算は終了する。ここで、UI スレッドにタスクをポストし、Chrome ウィンドウの表示状態を更新します。
  • この操作は、すべて同期ロックを使わずに行われるので、オクルージョンの計算は UI スレッドに最低限の影響しか与えない。たとえば、UI スレッドをブロックしてユーザー エクスペリエンスを悪化させることはありません。
  • 実装についてさらに詳しく知りたい方は、ドキュメントをご覧ください。


    オクルージョンの計算タイミングの決定

    オクルージョンの計算をし続けると、Chrome のパフォーマンスが低下することになるので、それは避けたいことです。つまり、ウィンドウが表示対象またはオクルージョン対象になるタイミングを検知する必要があります。ありがたいことに Windows では、ウィンドウの移動、リサイズ、最大化、最小化などのさまざまなシステム イベントをトラッキングできます。オクルージョン計算スレッドは、これらのイベントを追跡したいことを Windows に伝えます。そしてイベントが通知されると、イベントを精査して新たにオクルージョン計算を行うかどうかを決定します。非常に短い時間内に複数のイベントを受け取る可能性があるため、オクルージョンの計算は 16 ミリ秒に 1 回を超える頻度では行いません。この時間は、フレームレートが 1 秒あたり 60 フレーム(fps)である場合に 1 フレームが表示される時間に対応します。

    リッスンするイベントは、ウィンドウのアクティブ化や非アクティブ化、ウィンドウの移動やリサイズ、ユーザーの画面ロックやロック解除、モニターの電源オフなどです。オクルージョンの計算は必要以上に行いたくありませんが、ウィンドウが表示されるイベントを見逃すわけにはいきません。見逃してしまうと、ウェブ コンテンツが表示されるはずの場所が白くなってしまうからです。これは絶妙なバランスです [3]

    リッスンするイベントは、Chrome ウィンドウがオクルージョンされるかどうかに関わるものです。たとえば、マウスを動かすとたくさんのイベントが発生し、カーソルも点滅するたびにイベントを発行しています。そういったイベントはウィンドウ オブジェクトとは関係ないので、無視します。また、ツールチップの表示によってオクルージョンの計算がトリガーされることはないので、大半のポップアップ ウィンドウのイベントも無視します。

    オクルージョン スレッドは、さまざまな Windows イベントを検知したいことを Windows に伝えます。UI スレッドは、主要な状態変化(モニターの電源オフ、ユーザーによる画面ロック)が発生した場合にそれを検知したいことを Windows に伝えます。





    結果

    この機能は、効果を測定する実験と合わせて開発され、2020 年 10 月に M86 リリースの一部としてすべての Chrome Windows ユーザーにロールアウトされました。指標から、この機能をオンにした場合にパフォーマンスが大幅に改善されることがわかります。
    • 起動時間が 8.5% から 25.8% 短縮
    • GPU メモリ使用量を 3.1% 削減
    • レンダラー全体の描画フレーム数を 20.4% 削減
    • レンダラーのクラッシュが発生したクライアントが 4.5% 減少
    • First Input Delay(初回入力までの遅延時間)が 3.0% 向上
    • First Contentful Paint(視覚コンテンツの初期表示時間)と Largest Contentful Paint(最大視覚コンテンツの表示時間)が 6.7% 向上
    起動時間と初回入力までの遅延時間が改善したのは、Chrome が起動時に 2 つ以上の全画面ウィンドウを復元する場合、いずれかのウィンドウがオクルージョンされる可能性が高いためです。Chrome はそのウィンドウに関する大半の作業を省略できるので、より重要なフォアグラウンド ウィンドウのためにリソースを節約できます。

    すべての統計情報の出典 : Chrome クライアントから匿名で集計した実データ
    [1] 音声や動画を再生しているタブなど、一部のタブは優先度が下がりません。
    [2] 非矩形ウィンドウの計算は複雑です。これはあまり使われないと考えられていましたが、Windows 7 のデフォルト テーマの特性上、Windows 7 では一般的に使われています。
    [3] 最初にこれをリリースしたとき、Citrix で別のユーザーが画面をロックすると、Windows が現在のセッションではないセッションの変化通知を送信してくるため、白いウィンドウが表示されることがすぐにわかりました。詳細はこちらをご覧ください。

    Reviewed by Eiji Kitamura - Developer Relations Team

    Viewing all articles
    Browse latest Browse all 2207

    Trending Articles