プロンプトとコンテキスト
ユーザーからフィルターボタンをクリックした後にページがカクつくという報告があります。メインスレッドのLong Tasksを特定し、Interaction to Next Paint (INP) への影響を評価して、修正を検証する方法を説明してください。
入力遅延(input delay)、イベントハンドラーの処理(event-handler work)、次の描画(next paint)を区別してください。「debounceを追加する」や「Workerを使う」というのは診断ではありません。実ユーザーのエビデンス、ラボ環境のトレース、リグレッション指標、フォールバック境界まで網羅してください。
面接官がテストしていること
パフォーマンスモデル
優れた回答では、インタラクションを入力待ち、イベント処理、レンダリング、ペイントに分解し、ビジー状態のメインスレッドがブラウザのフィードバックを遅らせる理由を説明します。
エビデンスに基づく診断
推測するのではなく、PerformanceObserver、ブラウザのPerformanceトレース、インタラクションのコンテキストを使用して、スクリプト、コンポーネント、データサイズを特定します。
修正のトレードオフ
シリアライズと状態の整合性を考慮しながら、タスク分割、同期的処理の削減、仮想化、重要でない更新の遅延、Workerの活用について議論します。
実ユーザーによる検証
p75 INP、Long Task数、インタラクションのパーセンタイル、ビジネスのコンバージョンを比較します。ラボ環境のサンプルと、実デバイス、ネットワーク、低スペックCPUを区別します。
尋ねるべき確認の質問
- カクつきはすべてのインタラクションで発生していますか、それとも特定のフィルター条件のみですか?
- 対象となるデバイス、ブラウザ、データサイズは何ですか?
- 問題は初期読み込み、イベント処理、またはイベント後のレイアウトとペイントのどこにありますか?
- 実ユーザーのINP、イベント所要時間、Long Taskのサンプルは存在しますか?
- 結果は同期的に更新される必要がありますか、それとも計算が完了する前にUIが応答することは可能ですか?
- ソート、ページネーション、結果の精度を変更することは可能ですか?
30秒の回答フレームワーク
「実ユーザーのINPとインタラクションサンプルを使用して影響を受けているページを特定し、同じデバイスとデータサイズでPerformanceトレースを記録します。PerformanceObserverで50msを超えるLong Tasksを収集でき、トレースによってコールスタックとペイントフェーズを特定します。同期的なイベント処理が大きすぎる場合は、タスクを分割し、再レンダリングを減らし、リストを仮想化します。メッセージやシリアライズのコストを含め、メリットがある純粋なCPU処理についてのみWorkerの利用を検討します。その後、p75 INP、インタラクションのLong Task、コンバージョンを比較します。」
ステップごとの詳細解説
ステップ 1: ベースラインの確立
p75 INP、イベント所要時間、次の描画遅延、Long Task数、エラーをページ、インタラクション、デバイス、リリースごとにセグメント化します。高速なローカルマシンは母集団のベースラインにはなりません。
ステップ 2: 再現と特定
ブラウザのPerformanceパネルでフィルターのインタラクションを記録します。メインスレッドのフレームチャート、Long Tasks、レイアウト、ペイントを調査します。PerformanceObserverを使用すると、実行時のLong Taskエントリを収集し、ページ、インタラクション、リリースのコンテキストを付与できます。
ステップ 3: ボトルネックの分離
長い入力待ちは先行する同期タスクを示し、長いイベント処理はパース、フィルタリング、状態更新を示し、長いペイントはレイアウト、スタイル、または肥大化したDOMを示します。INPは入力から次の描画までの全体の経路であり、単一の関数の所要時間ではありません。
ステップ 4: 同期的処理の削減
ページネーション、仮想化、インクリメンタルフィルタリング、キャッシングにより、計算と再レンダリングを削減します。ロギング、プリフェッチ、アナリティクスはインタラクションのクリティカルパスから外します。アイドル時間やチャンク分割によるスケジューリングは、アイドル時間が不足した場合の計画がある場合にのみ使用します。
ステップ 5: Workerの評価
Workerは、Transferableなデータまたは管理しやすいデータを伴う純粋なCPU処理に適しています。大きなデータのコピー、頻繁なメッセージング、DOMアクセスはパフォーマンス上のメリットを打ち消す可能性があります。結果にバージョンを付与し、古い処理をキャンセルして、古いフィルターが新しい状態を上書きしないようにします。
ステップ 6: 検証とリグレッション防止
代表的な低スペックデバイスやデータセットで再現確認を行い、段階的にロールアウトします。p75/p95 INP、Long Task数、インタラクション完了率、キャンセル率、コンバージョンを比較します。リグレッションを検知してアラートを出す、またはブロックするパフォーマンスバジェットを設定します。
質の高い模範解答
「まず実ユーザーデータを使用して、問題が集中しているインタラクション、デバイス、リリースを特定し、同じデータサイズでフィルター処理を記録します。トレースから配列のフィルタリング、状態更新、リストのレイアウトが1つのハンドラー内で行われていることが判明した場合、フィルタリングをキャッシュし、リストを仮想化し、重要でない処理を遅延させます。
PerformanceObserverで50msを超えるLong Tasksを収集し、ページやインタラクションと関連付けます。フィルタリングが依然として純粋なCPUボトルネックである場合は、それをWorkerに移行し、メッセージサイズを制限して古い結果を破棄します。低スペックデバイスで修正をカナリアリリースし、展開範囲を広げる前にp75 INP、Long Task数、キャンセル率、フィルター完了率を比較します。」
よくある間違い
- 平均レイテンシのみを見る → テールユーザーが見落とされる → デバイスごとにp75/p95 INPをセグメント化する。
- Long TaskをINPと同一視する → 入力とペイントが除外される → インタラクション全体のタイムラインをトレースする。
- あらゆるカクつきに対して安易にdebounceを追加する → 必要なフィードバックが遅れる可能性がある → まず計算、レンダリング、ネットワークのボトルネックを特定する。
- すべての処理をWorkerに移動する → コピーとメッセージングのコストが増大する → メリットのある純粋なCPU処理のみを移行する。
- 開発用ラップトップでのみテストする → 低スペックデバイスで依然としてカクつきが発生する → 代表的なデバイス、データ、ロールアウトコホートで再現確認する。
- キャンセル処理なしでチャンク分割を行う → 古い結果が新しい状態を上書きする → バージョン管理、キャンセル、コミットチェックを追加する。
- ラボ環境のLighthouseのみを使用する → 実際のインタラクションが見落とされる → 実ユーザーのINPとLong Tasksをサンプリングする。
- 修正後にパフォーマンスバジェットを設定しない → リグレッションが見過ごされる → しきい値を設定し継続的に監視する。
フォローアップの質問と回答
フォローアップ 1: Long Taskは60msしかありません。なぜINPが依然として悪いのですか?
入力待ち、ハンドラー後のレイアウトとペイント、および隣接するタスクを調査してください。INPは応答経路全体を対象としており、単一の60msのタスクだけが原因のすべてとは限りません。
フォローアップ 2: Workerを使用したことで結果が遅くなった場合はどうしますか?
シリアライズ、データ転送、スケジューリングを測定します。小さなデータにはメインスレッドのファストパスを維持し、大きなメッセージはバッチ処理するかArrayBuffer等の転送(Transferable Objects)を使用し、不要になったリクエストはキャンセルします。
フォローアップ 3: Long Tasksの発生元はどのように観測しますか?
PerformanceObserverで開始時刻、所要時間、ページ、リリースを記録し、コールスタックについてはPerformanceトレースを使用します。機密性の高いユーザー入力は絶対にログに記録しないでください。
フォローアップ 4: フィルタリングの応答を即座に感じさせる必要がある場合はどうしますか?
入力を受け付けたことを同期的にフィードバックし、プログレスを表示した上で、インクリメンタルに計算します。結果のバージョンをフィルター状態と一致させ、一時的な状態と完了状態を区別してUIに反映します。
フォローアップ 5: コンバージョンが損なわれていないことをどのように証明しますか?
変更をカナリアリリースし、明確な中断条件を設定した上で、デバイスおよびネットワークごとにp75 INP、完了率、キャンセル率、エラー、主要なコンバージョンを比較します。
出典 1: MDN パフォーマンスデータ
MDNは、Long Taskのレコードを50ms以上続くタスクと定義しており、メインスレッドのブロックに関する実行時のエビデンスを提供します。
出典 2: PerformanceObserver
MDNにはPerformanceObserverを使用したパフォーマンスエントリの監視に関するドキュメントがあり、実行時のLong Tasksおよびリリースコンテキストの収集をサポートしています。
出典 3: web.dev Long Tasks and INP
web.devでは、Long Tasksがメインスレッドをブロックしてフィードバックを遅らせる仕組みを解説し、タスク分割、同期的処理の削減、Workerの評価を推奨しています。また、INPがインタラクションから次の描画までの応答性を捉える指標であることを説明しています。