本文へスキップ

記録と CI の予算 ​

npx myaku record は Myaku を注入した Chrome か Edge でゲームを動かし、フレーム時間のパーセンタイルと最悪のヒッチを解説つきで出力します。予算を設定すれば、ゲームが超えたときに失敗するので、フレーム時間の悪化がテストの失敗と同じようにビルドを止めてくれます。

bash
npm run build
npx myaku record dist --seconds 20 --cpu 4 --p95 20 --hitches 6
frames   1190 in 20.0 s · 60 fps · budget 25.0 ms
frame    p50 16.7 ms · p95 17.1 ms · p99 33.2 ms · max 41.0 ms
code     p50 3.1 ms · p95 6.4 ms
hitches  2 (6.0/min) · upload 1, script 1

worst hitches
  upload · high  Frame 812 took 41 ms (budget 25 ms). 3 uploads sent 12 MB to the GPU this frame.
    Create and upload textures in the load step, or spread them over several frames.

budgets
  ✔ p95 frame time (ms): 17.1 (limit 20)
  ✔ hitches per minute: 6 (limit 6)

ゲームを変更する必要はありません。 Myaku はページの読み込み中、ゲーム自身のスクリプトより前に注入されるので、Myaku を含まない本番ビルドでも動きます。

記録できるもの ​

  • フォルダ(デフォルトは dist):ローカルで配信します。本番ビルドです。
  • URL:開発サーバー、プレビューデプロイ、ステージング。

プレイスクリプトがなければ、Myaku はゲームが勝手にやることを記録します。タイトル画面、デモ画面、ベンチマークシーンなどです。実際のプレイをプロファイルするなら、プレイスクリプトを追加してください。

ゲームを遊ばせる:--play ​

プレイスクリプトは、Playwright の page を受け取る関数を default export するモジュールです。キーを押したり、ボタンをクリックしたり、待ったりします。

js
// play.mjs
export default async function play(page) {
  await page.mouse.click(400, 300); // Play を押す
  for (let i = 0; i < 20; i++) {
    await page.keyboard.press("Space");
    await page.waitForTimeout(250);
  }
}
bash
npx myaku record dist --seconds 10 --play play.mjs

オプション ​

オプション
--seconds <n>記録する秒数(デフォルト 10)
--warmup <n>読み込み後、記録を始めるまで待つ秒数。起動処理を数えないためです(デフォルト 1)
--cpu <n>CPU を n 倍遅くします。4 でだいたいミドルレンジのスマホくらいです
--viewport <WxH>ウィンドウサイズ(デフォルト 1280x720)。縦持ちのスマホなら 390x844 など
--play <file>プレイスクリプト(上記)
--headedブラウザのウィンドウを表示します
--traceChrome のフレームパイプラインも記録します。下記を参照
--trace-out <file>--trace と併用し、Chrome DevTools や Perfetto 用に生のトレースを保存します
--p95 <ms>、--p99 <ms>フレーム時間のそのパーセンタイルが上限を超えたら失敗します
--hitches <n>1 分あたりのヒッチ数がこれを超えたら失敗します
--json、--out <file>レポート全体と予算の結果を JSON で出力します

終了コード:0 は予算内、1 は予算超過、2 はエラー(ビルドがない、サーバーが動いていない、ブラウザがない)。

実際に画面に出たもの:--trace ​

ページから見えるのは requestAnimationFrame だけです。--trace を付けると、プレイ中の Chrome 自身のフレームパイプラインと GPU プロセスも記録し、Myaku の結果と照らし合わせます。

  • 表示されたフレーム。 trace.presentedMs は、ディスプレイが実際に表示したフレーム間の時間のパーセンタイルを、rAF ベースの値と並べて、表示数とドロップ数つきで示します。
  • ヒッチの確認。 各ヒッチは、確認済み(新しいフレームのないままリフレッシュが 1 回過ぎた)か、画面上では見えなかった(rAF は遅れたが、どのリフレッシュにもフレームが間に合った)かに分けられます。trace.missed は、Myaku のヒッチ一覧が拾えなかった画面の空白を挙げます。
  • GPU とコンポジターの原因。 トレースで理由がわかれば、unknown のヒッチは gpu か compositor になります。
  • 本当のリフレッシュレート。 ディスプレイのレートに一度も届かないゲームでは、ページはディスプレイが実際より遅いと思い込みます。トレースは本当のレートを知っているので、予算もそこから決まります。
sh
npx myaku record dist --trace --trace-out trace.json

デフォルトではオフで、Chromium 専用です。ページには何の変化もありません。私たちのテスト用ゲームでは、トレースありとなしでフレーム時間は同じでした。

CI で使う ​

yaml
# .github/workflows/perf.yml
- run: npm ci && npm run build
- run: npx myaku record dist --seconds 20 --cpu 4 --p95 22 --hitches 10 --out myaku.json
- uses: actions/upload-artifact@v4
  if: always()
  with: { name: myaku, path: myaku.json }

フレーム時間はマシンによって変わります。同じ CI ランナーで何度か Myaku を動かし、見えた値より少し上に予算を設定して、ゲームが速くなるにつれて締めていきましょう。ホステッドランナーはノイズが多いので、厳しい --p99 より --hitches のほうが警報線として優秀です。

Myaku はマシンにインストールされている Chrome か Edge を使います(GitHub の Ubuntu ランナーには Chrome があります)。ブラウザを選ぶには、MYAKU_BROWSER にブラウザの実行ファイルを指定してください。