応答性の指標の改善に向けて

応答性の測定に関する Google の見解を学び、フィードバックをお寄せください。

Annie Sullivan(アニー・サリバン)
Annie Sullivan
ホンボソン
Hongbo Song
ニコラス ペニャ モレノ
Nicoás Peña Moreno

Google は、Chrome 速度指標チームにおいて、ウェブページがユーザー入力にどれだけ早く反応するかについての理解を深めようと取り組んでいます。応答性の指標を改善するためのアイデアをいくつか共有し、フィードバックをお寄せください。

この投稿では、次の 2 つの主なトピックを取り上げます。

  1. 現在の応答性指標である初回入力遅延(FID)を確認し、いくつかの代替値ではなく FID を選択した理由を説明します。
  2. 個々のイベントのエンドツーエンドのレイテンシをより正確にキャプチャするために、検討してきた改善点を紹介します。また、これらの改善は、ページのライフサイクル全体におけるページの全体的な応答性をより包括的に把握することを目的としています。

First Input Delay とは

First Input Delay(FID)指標は、ブラウザでページ上の最初のユーザー操作の処理を開始するまでの時間を測定します。特に、ユーザーがデバイスを操作してから、ブラウザが実際にイベント ハンドラの処理を開始できるようになるまでの差を測定します。FID はタップとキーの押下に対してのみ測定されます。つまり、次のイベントの最初の発生のみが考慮されます。

  • click
  • keydown
  • mousedown
  • pointerdown(後に pointerup が続く場合のみ)

次の図は、FID を示しています。

First Input Delay は
入力が発生してから入力が処理可能になるまでの

FID には、これらのイベント ハンドラの実行にかかった時間や、その後ブラウザが画面を更新するために行った作業は含まれません。入力を処理する機会が得られるまでメインスレッドがビジー状態だった時間を測定します。通常、このブロック時間の原因は長い JavaScript タスクです。これらのタスクはいつでも停止できないため、ブラウザが入力の処理を開始する前に現在のタスクを完了する必要があります。

FID を選択した理由

Google は、実際のユーザー エクスペリエンスを測定することが重要であり、指標の改善がユーザーに真のメリットをもたらすことを保証すると考えています。FID を測定することにしたのは、読み込まれたばかりのサイトをユーザーが操作しようとしたときのユーザー エクスペリエンスの一部を示すためです。FID は、ユーザーがサイトとやり取りした際のレスポンスを確認するために待つ必要がある時間の一部をキャプチャします。つまり FID は、ユーザーが操作を行った後に待機する時間の下限です。

Total Blocking Time(TBT)Time To Interactive(TTI)などの他の指標は、長いタスクに基づいており、FID と同様に、読み込み中にメインスレッドのブロック時間を測定します。これらの指標はフィールドとラボの両方で測定できるため、なぜ FID よりも片方が好ましくないのかという質問が多くのデベロッパーから寄せられました。

これにはいくつかの理由があります。おそらく最も重要な理由は、これらの指標はユーザー エクスペリエンスを直接測定しないことです。これらの指標はすべて、ページで JavaScript がどの程度実行されるかを測定します。JavaScript の長時間実行はサイトに問題を引き起こす傾向にありますが、そのようなタスクの発生時にユーザーがページを操作していない場合、必ずしもユーザー エクスペリエンスに影響することはありません。TBT と TTI で高いスコアを獲得しているページでも、処理が遅く感じられる場合や、ユーザーにとっては速いと感じながらスコアが低くなる場合もあります。Google の経験上、こうした間接的な測定により、一部のサイトでは有効に機能する指標が得られますが、ほとんどのサイトではそうではない指標が導き出されます。要するに、長いタスクと TTI はユーザー中心ではないため、これらの候補は有用ではありません。

ラボ測定は重要な診断ツールであり、非常に貴重なものですが、本当に重要なのは、ユーザーがサイトをどのように体験しているかです。実際のユーザーの状況を反映するユーザー中心の指標を使用することで、エクスペリエンスに関する有意義な情報を確実に捉えることができます。まずはエクスペリエンスのごく一部から始めることにしましたが、この部分はエクスペリエンス全体を網羅するものではありません。そのため、ユーザーが入力が処理されるのを待つ時間の大部分をキャプチャするように取り組んでいます。

現場での TTI 測定に関する注意事項

実際のユーザーの TTI を測定することは、ページの読み込み後の非常に遅い段階で発生するため、問題があります。TTI を計算する前に、5 秒間のネットワーク停止時間枠が必要です。ラボでは、必要なデータがすべて揃ったときにページをアンロードするように選択できますが、現場でのリアルタイム ユーザー モニタリングではそうではありません。ユーザーはいつでもページから離れることや、ページを操作することができます。特に、読み込みに時間がかかるページはユーザーが離れることがあり、その場合は正確な TTI が記録されません。Chrome で実際のユーザーの TTI を測定したところ、TTI に到達したページ読み込みは約半分であることがわかりました。

どのような改善を検討していますか?

Google は、FID が現在測定している指標を拡張しつつ、ユーザー エクスペリエンスとの強い関連性を保ち続ける新しい指標を開発したいと考えています。

新しい指標は次のように求めます。

  1. 最初の入力だけでなく、すべてのユーザー入力の応答性を考慮する
  2. 遅延だけでなく、各イベントの完全な時間をキャプチャします。
  3. 同じ論理ユーザー操作の一部として発生するイベントをグループ化し、その操作のレイテンシをすべてのイベントの最長時間として定義します。
  4. ページのライフサイクル全体を通じて発生したすべてのインタラクションの集計スコアを作成します。

成功するためには、この新しい指標のスコアが低いサイトは、ユーザーの操作にすぐに反応しない、という確信を持って言える必要があります。

全アクティビティの時間を取得

1 つ目の明らかな改善は、イベントのエンドツーエンドのレイテンシをより広い範囲に捉えようとすることです。前述のように、FID は入力イベントの遅延部分のみをキャプチャします。ブラウザが実際にイベント ハンドラを処理するのにかかる時間は考慮されていません。

次の図に示すように、イベントのライフサイクルにはさまざまなステージがあります。

イベントのライフサイクルの 5 つのステップは

Chrome が入力を処理する手順は次のとおりです。

  1. ユーザーによる入力が行われる。これが発生する時刻はイベントの timeStamp です。
  2. ブラウザでヒットテストを実行して、イベントがどの HTML フレーム(メインフレームまたは一部の iframe)に属しているかを判断します。次に、ブラウザは、その HTML フレームを管理する適切なレンダラ プロセスにイベントを送信します。
  3. レンダラはイベントを受信し、キューに入れて、使用可能になったときに処理できるようにします。
  4. レンダラはハンドラを実行してイベントを処理します。これらのハンドラは、入力処理の一部である追加の非同期処理(setTimeout やフェッチなど)をキューに入れることができます。ただし、この時点で同期処理は完了しています。
  5. イベント ハンドラの実行結果を反映したフレームが画面に描画されます。イベント ハンドラによってキューに入れられた非同期タスクは、未完了である可能性があります。

上記のステップ(1)と(3)の間の時間はイベントの遅延で、FID はこれを測定します。

上記のステップ(1)と(5)の間の時間がイベントの「期間」です。これが新しい指標で測定される値です

イベントの期間には遅延も含まれますが、これにはイベント ハンドラ内で行われる処理と、イベント ハンドラの実行後に次のフレームをペイントするためにブラウザが行う必要がある作業も含まれます。イベントの所要時間は現在、Event Timing API でエントリの duration 属性を介して確認できます。

非同期タスクに関する注意事項

イベントによってトリガーされる非同期処理もキャプチャできれば理想的です。しかし、問題は、イベントによってトリガーされる非同期処理を正しく定義するのがきわめて難しいことです。たとえば、デベロッパーはイベント ハンドラでアニメーションを開始し、setTimeout を使用してアニメーションを開始できます。ハンドラに投稿されたすべてのタスクをキャプチャすると、アニメーションが実行されている間、完了時間が遅延します。ヒューリスティックを使用して非同期の作業をキャプチャし、できるだけ早く完了する必要がある作業については、オプションを調査することが重要であると Google は考えています。ただし、完了までに長い時間がかかる作業にはペナルティが課されないため、慎重に行う必要があります。したがって、最初の作業ではステップ 5 をエンドポイントと見なします。つまり、同期処理と、そのような処理が完了した後にペイントされるまでにかかる時間のみを考慮します。つまり、最初の作業のステップ 4 で非同期に開始される作業は、ヒューリスティックを適用して推測しません。

多くの場合、処理は同期的に実行する必要があることに注意してください。実際は、イベントが順番にディスパッチされることがあり、イベント ハンドラを順番に実行する必要があるため、これが避けられない場合があります。とはいえ、取得をトリガーするイベントや、次の requestAnimationFrame コールバックで行われる重要な処理に依存するイベントなど、重要な処理は見逃す可能性があります。

イベントをインタラクションにグループ化

最初のステップとして、指標の測定を遅延から所要時間に拡大することが推奨されますが、それでも指標には重大なギャップが残ります。重要なのは、ページを操作するユーザー エクスペリエンスではなく、個々のイベントです。

1 回のユーザー操作の結果として、さまざまなイベントが発生する可能性があるため、それぞれを個別に測定しても、ユーザー エクスペリエンスを明確に把握することはできません。Google は、タップ、キーの押下、スクロール、ドラッグにおいて、ユーザーがレスポンスを待機する時間全体を、指標でキャプチャする必要があります。そこで、それぞれのレイテンシを測定するインタラクションのコンセプトを導入します。

操作のタイプ

次の表に、定義する 4 つのインタラクションと、それらに関連付けられている DOM イベントを示します。これは、そのようなユーザー操作が発生したときにディスパッチされるすべてのイベントのセットとはまったく同じではありません。たとえば、ユーザーがスクロールするとスクロール イベントはディスパッチされますが、画面がスクロールを反映するように更新された後に発生するため、インタラクション レイテンシには含めません。

インタラクション 開始 / 終了 パソコン版イベント モバイル イベント
キーボード キーが押されました keydown keydown
keypress keypress
鍵が解放されました keyup keyup
タップまたはドラッグ [開始] または [開始] をタップ pointerdown pointerdown
mousedown touchstart
上をタップするか、端をドラッグします pointerup pointerup
mouseup touchend
click mousedown
mouseup
click
スクロール なし
各インタラクション タイプの DOM イベント

現在、上記の最初の 3 つの操作(キーボード、タップ、ドラッグ)は FID の対象です。新しい応答性の指標では、スクロールも含める必要があります。スクロールはウェブで非常に一般的であり、ユーザーにとってページの応答性がどう感じられるかを示す重要な要素であるためです。

開始と終了に関する注意事項

これらの操作は、ユーザーがマウス、指、またはキーを押しているときと、指を持ち上げるときという 2 つの部分に分かれています。ユーザーがこれら 2 つのアクションの間でユーザーが指を離した時間をページのレイテンシの一部としてカウントしないようにする必要があります。

キーボード

キーボード操作は、ユーザーがキーを押すと離すという 2 つの部分で構成されます。 このユーザー インタラクションには、keydownkeyupkeypress の 3 つの関連イベントがあります。次の図は、キーボード操作の keydownkeyup の遅延と持続時間を示しています。

互いに素なイベント期間に対するキーボード操作

上の図では、keydown 更新のフレームが keyup の発生前に提示されるため、継続時間が互いに素な状態です。ただし、常にそうである必要はありません。また、フレームの生成に必要な最後のステップはレンダラ プロセスの外部で行われるため、レンダラ プロセスのタスクの途中でフレームが表示される場合があります。

keydownkeypress はユーザーがキーを押したときに発生し、keyup はユーザーがキーを離したときに発生します。通常、メイン コンテンツの更新はキーが押されたときに行われます。つまり、画面にテキストが表示されるか、修飾子効果が適用されます。とは言え、keyup でも興味深い UI の更新を提示するまれなケースを把握して、全体的な所要時間を確認したいと考えています。

キーボード操作にかかった合計時間を取得するには、keydown イベントと keyup イベントの最長時間を計算します。

キー入力の繰り返しに関する注意事項

ここで注目すべきエッジケースがあります。ユーザーがキーを押した後、キーを離すまでに時間がかかる可能性があります。この場合、ディスパッチされるイベントの順序は異なる可能性があります。このような場合、keydown ごとに 1 つのインタラクションが存在すると見なされ、対応する keyup が存在する場合と存在しない場合があります。

タップ

もう 1 つの重要なユーザー インタラクションは、ユーザーがウェブサイトをタップまたはクリックしたときです。上の図に示すように、keypress と同様に、ユーザーが押すとトリガーされるイベントと、離すとトリガーされるイベントがあります。タップに関連するイベントは、パソコンとモバイルで若干異なります。

タップまたはクリックの場合、通常はリリースがほとんどのリアクションをトリガーするものですが、キーボード操作と同様に、完全なインタラクションをキャプチャする必要があります。この場合は、タップ操作時に UI が更新されることはそれほど珍しいものではないため、そうすることがより重要です。

これらのイベントすべてにイベント期間を含めても、多くのイベントが完全に重複するため、インタラクション全体をカバーするために pointerdownpointerupclick のみを測定する必要があります。

pointerdownpointerup だけに絞り込むことはできますか?

まず、pointerdown イベントと pointerup イベントを使用して、対象となるすべての期間をカバーしていると想定します。残念ながら、このエッジケースが示すように、これは当てはまりません。モバイルまたはモバイル エミュレーションでこのサイトを開き、「ここをクリック」と表示された場所をタップしてください。このサイトによりブラウザタップの遅延がトリガーされます。pointerdownpointeruptouchend は迅速にディスパッチされ、mousedownmouseupclick はディスパッチされるまで遅延を待機します。つまり、pointerdownpointerup のみを確認した場合、合成イベントの所要時間が欠落することになります。合成イベントの所要時間はブラウザのタップの遅延が原因で大きいため、含める必要があります。そのため、pointerdownpointerupclick を測定して、インタラクション全体をカバーする必要があります。

抗力

ドラッグも関連するイベントが多く、サイトの UI の重要な更新につながることが一般的であるため、ドラッグも含めることにしました。しかし、今回の指標では、ドラッグの開始と終了(ドラッグの最初の部分と最後の部分)のみを考慮します。これは、推論が容易になるとともに、レイテンシを、考慮されている他の操作と同等にするためです。これは、mouseover などの継続的なイベントを除外するという Google の決定と一致しています。

また、Drag and Drop API で実装されたドラッグは、パソコンでしか機能しないため、考慮していません。

スクロール

サイトの操作の最も一般的な形の 1 つがスクロールです。新しい指標では、ユーザーの最初のスクロール操作のレイテンシを測定します。特に、ユーザーがスクロールをリクエストしたときのブラウザの最初の反応に着目します。スクロール操作全体について説明することはできません。つまり、スクロールすると多くのフレームが生成されるため、スクロールの反応として生成される最初のフレームに注目します。

1 つ目だけなのはなぜですか?まず、後続のフレームは個別のスムーズネス提案によってキャプチャできます。つまり、ユーザーにスクロールの最初の結果が表示された時点で、残りの結果は、スクロール エクスペリエンスがどの程度スムーズに感じられるかという観点で測定する必要があります。そのため Google では スムーズ化の取り組みによって これをより正確に捉えられると考えていますしたがって、FID と同様に、個別のユーザー エクスペリエンス、つまり、関連する明確な時点があり、レイテンシを簡単に計算できるユーザー エクスペリエンスを重視します。スクロール全体は連続的なものであるため、この指標でそのすべてを測定することは意図していません。

スクロールを測定する理由は何でしょうかChrome で収集したスクロールのパフォーマンスから、スクロールは通常非常に高速であることがわかりました。とは言え、さまざまな理由から、新しい指標に初期スクロール レイテンシを含めることも必要です。まず、スクロールが高速になるのは、それが重要であるため、十分に最適化されているからです。しかし、ブラウザによるパフォーマンス向上の一部をウェブサイトが回避する方法はまだあります。Chrome で最も一般的なのは、メインスレッドで強制的にスクロールを発生させることです。したがって、指標では、これがいつ発生し、ユーザーのスクロール パフォーマンスが低下する原因であるかがわかるはずです。2 つ目は、スクロールは無視できないほど重要すぎることです。スクロールを除外すると、ウェブ デベロッパーが適切に気付かないうちにスクロールのパフォーマンスが時間の経過とともに低下し、大きな盲点になってしまうことが懸念されます。

touchstarttouchmovescroll など、ユーザーがスクロールしたときにディスパッチされるイベントがいくつかあります。スクロール イベントを除き、これはスクロールに使用されるデバイスに大きく依存します。タッチイベントはモバイル デバイスで指でスクロールしたときにディスパッチされ、ホイール イベントはマウスホイールでスクロールしたときに発生します。スクロール イベントは、最初のスクロールが完了すると発生します。通常、ウェブサイトで非パッシブなイベント リスナーを使用している場合を除き、DOM イベントはスクロールをブロックすることはありません。スクロールは DOM イベントから 完全に切り離されたものだと考えています測定対象は、ユーザーがスクロール操作に十分な動作をしてから、スクロールが発生したことを示す最初のフレームまでの時間です。

インタラクションのレイテンシを定義する方法

前述のように、「下」と「上」のコンポーネントを含むインタラクションは、ユーザーが指を長押しした時間をアトリビューションすることを避けるために、別々に検討する必要があります。

このようなインタラクションでは、関連するすべてのイベントの継続時間をレイテンシに関与させます。インタラクションの「下側」と「上側」の各部分のイベント期間は重複する可能性があるため、これを実現するインタラクション レイテンシの最も単純な定義は、それに関連するイベントの最大継続時間です。前のキーボードの図では、keyup よりも長いため、keydown の時間の長さになります。

最大時間をハイライト表示したキーボード操作

keydownkeyup の期間も重複している可能性があります。これは、次の図のように、両方のイベントに表示されるフレームが同じ場合に発生することがあります。

キーボード操作では
長押しと離すのが同じフレームで行われます

最大数を使用する方法には長所と短所があるため、ぜひフィードバックをお寄せください

  • メリット: 単一の期間値のみを測定するという点で、スクロールの測定方法と一致します。
  • メリット: keyup が通常何もしないキーボード操作や、ユーザーがキーの押下と離を素早く、またはゆっくりと実行するようなケースで、ノイズを減らすことを目的としています。
  • デメリット: ユーザーの待ち時間全体を取得できません。たとえば、ドラッグの開始または終了をキャプチャしますが、両方をキャプチャすることはできません。

スクロール(関連付けられたイベントが 1 つだけある)の場合、そのレイテンシを、ブラウザがスクロールの結果として最初のフレームを生成するのにかかる時間として定義します。つまり、レイテンシは、スクロールをトリガーするのに十分な大きさの最初の DOM イベント(指を使用する場合は touchmove など)のイベント timeStamp と、スクロールが行われたことを反映する最初のペイントとの差分です。

ページごとのすべてのインタラクションを集計する

インタラクションのレイテンシを定義したら、ページ読み込みの集計値を計算する必要があります。ページ読み込みには、多くのユーザー インタラクションが存在する可能性があります。集計値を使用することで、次のことが可能になります。

  • ビジネス指標との相関関係を形成する。
  • 他のパフォーマンス指標との相関関係を評価する。理想的には、新しい指標は十分に独立し、既存の指標に付加価値を与えることが理想的です。
  • 理解しやすい方法で、ツールの値を簡単に公開できます。

この集計を行うには、次の 2 つの質問に答える必要があります。

  1. どのような数値を集計しようとしているか?
  2. それらの数値をどのように集計すればよいでしょうか。

現在、いくつかのオプションを検討、評価しております。この集計に関するご意見をお待ちしております。

1 つの方法は、インタラクションのレイテンシに対する予算を定義することです。これは、その種類(スクロール、キーボード、タップ、ドラッグ)によって異なります。たとえば、タップのバジェットが 100 ms でタップのレイテンシが 150 ms の場合、そのインタラクションのバジェット超過量は 50 ms となります。この場合、ページでのユーザー インタラクションのバジェットを超えるレイテンシの最大量を計算できます。

また、ページのライフサイクル全体におけるインタラクションの平均レイテンシまたは中央値を計算する方法もあります。したがって、レイテンシが 80 ミリ秒、90 ミリ秒、100 ミリ秒の場合、ページの平均レイテンシは 90 ミリ秒になります。また、インタラクションの種類に応じて異なる期待値を考慮して、「予算超過」の平均または中央値を検討することもできます。

ウェブ パフォーマンス API ではどのように表示されますか?

Event Timing にはない機能

残念ながら、この投稿で紹介したすべてのアイデアが Event Timing API を使用して捕捉できるとは限りません。特に、特定のユーザー アクションに関連するイベントを把握する簡単な方法はありません。そのために、API に interactionID を追加することを提案しました。

Event Timing API のもう 1 つの欠点は、スクロール操作を測定する方法がないことです。そのため、Google ではこれらの測定を有効にするよう取り組んでいます(Event Timing または別の API 経由)。

今できること

現時点では、タップ/ドラッグとキーボード操作の最大レイテンシを計算できます。次のコード スニペットでは、これら 2 つの指標が生成されます。

let maxTapOrDragDuration = 0;
let maxKeyboardDuration = 0;
const observer = new PerformanceObserver(list => {
  list.getEntries().forEach(entry => {
    switch(entry.name) {
      case "keydown":
      case "keyup":
        maxKeyboardDuration = Math.max(maxKeyboardDuration,
            entry.duration);
        break;
      case "pointerdown":
      case "pointerup":
      case "click":
        maxTapOrDragDuration = Math.max(maxTapOrDragDuration,
            entry.duration);
        break;
    }
  });
});
observer.observe({type: "event", durationThreshold: 16, buffered: true});
// We can report maxTapDragDuration and maxKeyboardDuration when sending
// metrics to analytics.

フィードバック

web-vitals-feedback@googlegroups.com までメールにて、これらのアイデアに関するご意見をお聞かせください。