本文へスキップ

判定の読み方 ​

フレームのインターバル(次のフレームまでの時間)が予算を超えると、そのフレームはヒッチです。予算のデフォルトはディスプレイのフレーム間隔の 1.5 倍で、60 Hz なら 25 ms、120 Hz なら 12.5 ms、165 Hz なら 9.1 ms です。Myaku はフレームからディスプレイを測り、30 フレームごとに測り直し、見えた中でいちばん速いレートを保持し、間引かれた区間は無視します。起動が遅くても予算が倍になることはありません。

ヒッチにはそれぞれ判定が付きます。

json
{
  "frame": 1204,
  "intervalMs": 79,
  "budgetMs": 9.1,
  "cause": "script",
  "confidence": "high",
  "summary": "Frame 1204 took 79 ms (budget 9.1 ms). 80 ms was script: `spawnWave` in src/enemies.ts:88.",
  "hint": "This ran inside the game loop. Profile the function in the Performance panel, or spread the work over several frames.",
  "where": { "source": "http://localhost:5173/src/enemies.ts", "fn": "spawnWave", "line": 88, "char": -1 }
}

confidence は、直接の証拠が原因を示すときは high、強く示唆されるときは medium、答えではなく確かめるべき手がかりのときは low です。判定には evidence も含まれます。フレームのコードの時間、描画、アップロードとそのバイト数、コンパイル、ヒープの減少、レイアウトの時間、スクリプト、スパンです。

Myaku は次の順に原因をチェックし、最初に当てはまったところで止まります。

hidden ​

フレームの途中でタブがバックグラウンドに回りました。ゲームの問題ではありません。長い空白のあとにゲームが動き続けるべきでないなら、visibilitychange で一時停止してください。

throttled ​

ゲームがほとんど何もしておらず、ブラウザも長い処理を報告していないのに、遅いフレームが続いた状態です。ウィンドウが隠れていた、最小化されていた、省電力モードだったなどの理由で、ブラウザがフレームを間引いていました。計測するときは前面に出してください。

compile ​

プレイ中にシェーダーがコンパイルされたか、プログラムがリンクされました。マテリアルやエフェクトを初めて使うときによく起きます。シェーダーはロード中にウォームアップしておきましょう。

upload ​

1 フレームで 1 MB 以上が GPU に送られました。新しいテクスチャ、canvas テクスチャ(テキストがよくある犯人です)、大きなバッファなどです。アップロードはロード時に済ませるか複数フレームに分散し、テクスチャは使い回しましょう。

script ​

ゲームのコードの実行が長引きました。Chromium では、Long Animation Frames のエントリーが関数とファイルを示します。遅いコードがフレームコールバックなら、Myaku はゲームがそれを登録した場所を指します。

エンジンがループを持っている場合、遅いコールバックはエンジンのステップ関数なので、判定はエンジンのファイルを示します。そのときは Myaku のエンジンのスパンが、update と render のどちらが時間を使ったか、Phaser ならどのシーンかを教えてくれます。

原因を特定できない場合(ほかのブラウザ)でも、コードが予算の大半を使ったフレームは script の判定になり、時間のかかったスパンが示されます。

layout ​

スタイルの再計算とレイアウトがフレームの大きな割合を占めました。canvas の上の DOM を毎フレーム更新していないか、スタイルを変えた直後にレイアウトを読む(offsetWidth、getBoundingClientRect)コードがないかを探してください。

gc ​

ゲームのコードがほぼ暇なあいだにヒープが 1 MB 以上縮みました。ガベージコレクションです。フレームあたりのメモリ確保を減らしましょう。ベクトルや配列は使い回し(プール)、ホットループではクロージャや map/filter を避けます。Chromium 専用で、ブラウザがヒープを十分細かく報告するときだけ有効です。Myaku はそれを確かめ、GC が見えないときは unknown の判定でそう伝えます。

gpu ​

myaku record --trace のときだけ出ます。ゲームのコードは速かったのに、Chrome の GPU プロセスがフレームのあいだずっと忙しく、ゲームの canvas を待っていました。しかも直前のフレームでもゲームが GPU を忙しくさせていました。フレームあたりの描画を減らしましょう。方法は、ピクセルを減らすこと(解像度を下げる・フルスクリーンのパスを減らす)、シェーダーを軽くすること、オーバードローを減らすことです。GPU の負荷が軽いときの単発のストールは unknown のままで、そのサマリーにはドライバー、OS、ほかのアプリがおそらく原因だと書かれます。

compositor ​

myaku record --trace のときだけ出ます。ゲームのコードは速かったのに、Chrome のコンポジターが canvas を待つのではなく、ページのレイヤーの描画に時間を使いました。よくある原因は、ブラー、フィルター、トランスフォーム、不透明度のアニメーションを使った DOM を canvas の上に重ねていることです。合成レイヤーを減らすか、canvas をページで唯一の大きな要素にしてください。

unknown ​

ゲームのコードは速く、ほかに時間を説明できるものがありません。GPU の仕事、コンポジター、ほかのアプリであることが多く、myaku record --trace でどれかを見分けられます。ドローコールが多い(2,000 超)ときは、ヒントがバッチ処理を提案します。単発の unknown フレームは、たいていゲームの手の届かないところが原因です。

予算内のフレーム ​

遅くなかったフレームをクリックしたり explain したりすると、そのフレームの時間と予算つきで ok が返ります。