コンテンツにスキップ

ADR-0078: トップの Lighthouse の合否を、Metal の GPU と simulate のスロットリングで 5 回測った中央値で判定する

Status

承認

Context

トップの性能を変える作業で、同じ条件で合否を判定できるように、測る条件を決める必要がある。

  • PRD の性能の要求は、Lighthouse の Performance が 90 以上で、LCP が 2.5 秒以内であることを求める。条件は Moto G Power、Slow 4G 相当としか決めていない。
  • トップの最初の訪問は、この要求の対象から除く。2 回目以降の訪問のトップは、対象に含める。
  • ADR-0026 の承認の条件は、2 回目以降の訪問の LCP と Performance が要求を満たさなければ、ふつうの HTML を先に出し、「庭に入る」のボタンで庭を出す形に替えると決めている。
  • 本文をシステムフォントにした後のトップの値は、Metal と simulate で Performance が 92、Metal と devtools で 80〜82 だった。
  • トップの値は、pnpm run measure:top(scripts/measure-top-lighthouse.mjs)で測る。
    • 引数を付けないときは、Metal、simulate、2 回目以降の訪問で 5 回測り、中央値を出す。
    • --visit reduced-motion は、動きを減らす設定で庭を出さないトップを測る。
  • CI は Lighthouse を実行しない。合否は、手元の Mac で手動で測って判定する。
  • 庭は WebGL で描く。Metal は macOS の GPU で描き、macOS でだけ動く。SwiftShader は、GPU を使わずに CPU で描く。
    • CI の庭の E2E は、GPU に依らず同じ絵にするために SwiftShader で描く(packages/e2e/playwright.config.ts)。
    • PageSpeed Insights が GPU を使うかは確認していない。
  • 測った端末は Apple M2 である。M2 の GPU は Moto G Power の GPU より速いと推測する。比べて測ってはいない。
  • simulate は Lighthouse のデフォルトで、スロットリングを掛けずに読み込んだ記録から、遅い端末の値を推定する。devtools は、通信と CPU にスロットリングを掛けて読み込む。
    • Lighthouse のスロットリングの設定は、通信の遅延と帯域と CPU の倍率だけで、GPU の項目は無い(レポートの configSettings.throttling)。
    • PageSpeed Insights と Lighthouse の CLI のデフォルトは simulate である。
  • スクリプトは、観測した LCP と FCP の時刻(レポートの observedLargestContentfulPaint と observedFirstContentfulPaint)が同じ回を lcpIsFcp で示す。
    • スクリプトの median は、lcpIsFcp の回も含めて全ての回から取る。
    • 庭を出すトップの simulate では、lcpIsFcp の回は、庭の最初のフレームがページの最初の描画に入ったと推定された回である。この回は、LCP と Performance が実際より良く出る。
    • 庭を出さないトップでは、本文の描画が LCP になるので、どの回も lcpIsFcp になる。

Decision

トップの合否を、次の条件で pnpm run measure:top で測った値で判定する。
庭を出すトップは引数を付けずに、庭を出さないトップは --visit reduced-motion だけを付けて測る。
GPU、スロットリング、訪問、回数は、スクリプトの引数の今のデフォルトと同じである。
集計は、スクリプトの median と違い、庭を出すトップで lcpIsFcp の回を除いてから中央値を取る。スクリプトは、この中央値を judged に出す。

項目 条件
GPU Metal(macOS の GPU)
スロットリング simulate(Lighthouse のデフォルト)
回数と集計 5 回測り、庭を出すトップでは lcpIsFcp の回を除いて、Performance と LCP をそれぞれ中央値で判定する
訪問 2 回目以降の訪問。庭を出さないトップは --visit reduced-motion で同じ条件で測る
端末の画面と回線 Lighthouse のデフォルトの mobile(Moto G Power、Slow 4G)
  • GPU を Metal にするのは、多くの訪問者の端末は GPU で庭を描くと推測するためである。SwiftShader で測ると、GPU の無い環境で CPU が描く時間を測ることになる。
  • スロットリングを simulate にするのは、PRD の条件が Lighthouse のデフォルトの mobile を指し、PageSpeed Insights でも同じ方法で測り直せるためである。
  • 庭を出すトップでは、lcpIsFcp の回を除く。この回の値は推定の誤りで、合格の側に出るためである。
    • Performance と LCP で、同じ回を除く。
    • 残りの回が偶数のときは、中央の 2 つの値の平均を中央値にする。スクリプトの中央値と同じ取り方である。
    • 除いた回が 3 回以上のときは、5 回を 1 度だけ測り直す。
    • 測り直しても 3 回以上のときは、判定せず、そのことを記録する。
  • 庭を出さないトップでは、lcpIsFcp の回を除かない。
  • この条件では、庭を出すトップの LCP は 2.82 秒で、要求の 2.5 秒以内を満たさない。
  • devtools と SwiftShader の値は、合否に使わない。トップの性能を変える pull request には、参考の値として devtools の Metal の値を添える。simulate の推定が実際の読み込みより速く出たときに、気づけるためである。

承認の条件

運営者が、次の論点に答える。
答えが推奨と違うときは、題、Decision、Considered Options の「採用:」の行、docs/adr/index.md の題、スクリプトのデフォルトを、答えに合わせる。

  1. 合否に使う GPU。推奨は Metal。
  2. 合否に使うスロットリング。推奨は simulate。
  3. 回数と集計。推奨は 5 回の中央値で、庭を出すトップでは lcpIsFcp の回を除き、測り直しは 1 度だけにする。
  4. PRD の性能の要求を満たすために、庭の描画を軽くする作業を行うか。推奨は行わない。1 で Metal を選ぶと、SwiftShader の値は合否に入らないためである。Metal でも庭を出すトップの LCP は要求を満たさず、その扱いは ADR-0026 の承認の条件による。
  5. トップの性能を変える pull request に、参考の値として devtools の Metal の値を添えるか。推奨は添える。simulate の推定が実際の読み込みより速く出たときに、気づけるためである。

承認の後に行うことは、次の 3 つ。

  • PRD の「トップの最初の訪問は、この条件の対象から除く。」の項目の下に、次の 1 行を足す。

    トップの合否を判定する GPU、スロットリング、回数は、ADR-0078 にある。

  • apps/web/src/features/top-garden/README.md の「Lighthouse で測る」に、この ADR の条件で合否を判定することと、ADR-0078 へのリンクを足す。論点 5 の答えも、README の同じセクションに書く。
  • スクリプトが、--visit reduced-motion のほかでは、lcpIsFcp の回を除いた中央値と、除いた回数を出すようにする。測り直しと合否の判定は、人が行う。

Verification

develop の 4286172 をビルドし、pnpm run measure:top で測った。
端末は Apple M2 の macOS で、Lighthouse 13.6.0、HeadlessChrome 156 である。
ほかのコーディングエージェントのセッションが動いている状態で測り、ロードアベレージは 2.4〜7.3、benchmarkIndex は 2986〜3173 だった。

トップ GPU スロットリング 回数 Performance(中央値と範囲) LCP(中央値と範囲) TBT(中央値) lcpIsFcp の回
庭を出す Metal simulate 20 92(91〜97) 2.82 s(1.50〜2.87 s) 183 ms 2
庭を出す Metal devtools 10 81(81〜82) 3.59 s(3.58〜3.62 s) 247 ms 0
庭を出す SwiftShader simulate 5 62(58〜62) 1.51 s(1.50〜2.29 s) 5115 ms 5
庭を出す SwiftShader devtools 5 39(38〜39) 6.59 s(6.54〜6.62 s) 2522 ms 0
庭を出さない Metal simulate 5 100(100) 1.50 s(1.50〜1.51 s) 0 ms 5
庭を出さない Metal devtools 5 98(98) 1.90 s(1.90〜1.91 s) 0 ms 5
  • 庭を出す行は、2 回目以降の訪問を測った。
  • 庭を出すトップの Metal と simulate は、5 回ずつ 4 組を測った。組ごとの Performance の中央値は 92、93、92、92 だった。
  • 庭を出すトップの Metal と simulate の lcpIsFcp の 2 回は、Performance が 97 と 93、LCP が 1.50 秒と 2.27 秒だった。2 回を除いた 18 回は、Performance の中央値が 92、LCP の範囲が 2.82〜2.87 秒だった。
  • 庭を出すトップの Metal と devtools の 10 回は、値の分布が 1 つにまとまった。本文をシステムフォントにする前は、load が延びる回があり、値の分布が 2 つに分かれた。
  • 庭を出すトップの SwiftShader と simulate の 5 回は、全てが lcpIsFcp だった。
  • 最初の訪問、記事のページ、macOS 以外の端末は測っていない。

Considered Options

選択肢 強み 弱み
採用: Metal と simulate の 5 回の中央値 GPU で描く端末に近い。PRD の条件の Lighthouse のデフォルトで、PageSpeed Insights と同じ方法である。スクリプトの引数のデフォルトを変えずに済む macOS でしか測れない。LCP は推定の値で、20 回に 2 回は実際より良く出た。M2 の GPU で描くので、GPU で庭を描く時間を少なく見積もる
Metal と devtools の 5 回の中央値 実際にスロットリングを掛けて読み込むので、LCP が実際に描画した時刻になる。lcpIsFcp の回が出ず、10 回の範囲が simulate より狭い PageSpeed Insights と方法が違い、同じ値で測り直せない。macOS でしか測れない。M2 の GPU で描く
SwiftShader と simulate の 5 回の中央値 どの OS でも測れる。CI の庭の E2E と同じ描き方である 5 回とも lcpIsFcp で、LCP の値を判定に使えない。GPU の無い環境で CPU が描く時間を測り、GPU で描く端末の値と離れる
SwiftShader と devtools の 5 回の中央値 どの OS でも測れる。GPU の無い環境の値を測る GPU で描く端末の値と離れる
Metal と simulate で、lcpIsFcp の回を除かない スクリプトの中央値をそのまま判定に使える 推定の誤りの回が入ると、中央値が合格の側にずれる。2 回入ると、Performance の中央値は残り 3 回の最も良い値になる
回数を 5 回より増やす 外れ値の回の影響が減る 測る時間が延びる。Metal と simulate の 4 組では、組ごとの中央値の差が 1 だった
中央値の代わりに最も悪い値を使う 外れ値の回が判定に入る simulate の 1 回ごとのばらつき(91〜97)で合否が変わりうる

Consequences

Positive

  • トップの性能を変える作業で、同じ条件で合否を判定できる。
  • スクリプトの引数のデフォルトを変えずに済む。今までの Metal と simulate の値と、そのまま比べられる。

Negative

  • この条件でも、庭を出すトップの LCP は、要求の 2.5 秒以内を満たさない。ADR-0026 の承認の条件は、要求を満たさなければ「庭に入る」のボタンで庭を出す形に替えると決めている。替えずに済ませるには、ADR-0026 を置き換える新しい ADR が要る。
  • M2 の GPU で描くので、Moto G Power で庭を描く時間を少なく見積もる。
  • macOS の無い環境では、合否を判定できない。
  • GPU の無い端末と、GPU を使えないブラウザの訪問者の遅さは、合否に入らない。SwiftShader では、M2 の CPU でも庭の最初の描画に数秒かかる。PRD の性能の要求を満たすために、庭の描画を軽くする作業は行わない。
  • simulate の推定が、実際の読み込みより速く出ることがある。devtools の値を参考に添えないと、気づきにくい。