Myaku のご紹介
Web ゲームの開発者なら誰でも知っている瞬間があります。ゲームを遊んでいると、カクッとする。ほんの一瞬止まって、拍が飛んで、また滑らかに戻る。DevTools を開いて記録を始め、1分ほど遊んでみても、もう起きない。あるいは起きたとしても、目の前には1万本のバーが並ぶフレームチャート。どれが原因だったのか、途方に暮れる。
ほとんどのヒッチは、説明されないまま終わります。「ブラウザのせい」や遅いマシンのせいにされ、プレイヤーはそれと付き合い続けます。
Myaku(脈)は、それに対する私たちの答えです。ページではなく、ゲームのために作られたフレームプロファイラーです。
import "myaku/auto";エントリファイルの先頭にこの1行を書くだけで、ゲームの隅に小さなフレームグラフが現れます。赤いスパイクがヒッチです。ホバーするとグラフが止まり、スパイクをクリックすると、Myaku が何が起きたかを教えてくれます。
フレーム 1,204 は 79 ms かかりました(予算 9.1 ms)。うち 80 ms はスクリプト:src/enemies.ts:88 の
spawnWave。 これはゲームループの中で実行されました。Performance パネルでこの関数をプロファイルするか、処理を複数のフレームに分散させてください。
フレームチャートではなく、判定を
Myaku はプロファイルを読み解くことを求めません。遅いフレームのひとつひとつに判定を出します。原因、その確信度、そして試すべきこと。原因は、実際にゲームをカクつかせるものばかりです。
- あなたのスクリプト。ブラウザが報告してくれれば、関数名とファイルまで特定します。
- ガベージコレクション:コードが何もしていないのに、ヒープが数メガバイト減っています。
- GPU へのアップロード:プレイ中に作られたテクスチャやバッファを、バイト単位で数えます。
- シェーダーのコンパイル:エフェクトを初めて使ったときに起きます。
- レイアウト:canvas の上に重ねた DOM の UI が、毎フレーム再計算されています。
- ブラウザ自身:隠れたタブや、覆われたウィンドウがスロットリングされています。
そして何も説明がつかないときは、当て推量をせず、低い確信度でそう伝えます。
常にオン
開始しないといけないプロファイラーは、ヒッチを見逃すプロファイラーです。Myaku は直近10秒のフレームを常に保持しています。カクつきを感じたときには、もう記録されていて、オーバーレイに表示されています。
これはプロファイラーが軽くないと成り立ちません。Myaku は固定サイズの型付き配列にフレームを記録するので、フレームごとのメモリ確保がなく、自分が探しているガベージコレクションを自分で引き起こすこともありません。自身のコストも測って報告します。私たちのテスト用ゲームでは、1フレームあたり約 0.05 ms でした。
どのエンジンでも
Myaku はゲームを外側から見守ります。requestAnimationFrame、canvas のコンテキスト、そしてブラウザが報告するもの。なので Phaser、PixiJS、three.js、KAPLAY、Excalibur、自分で書いたループ、そして debuff で、ゲームに手を入れることなく動きます。
Phaser の Runner サンプルで試しました。ある関数を1フレームだけ 80 ms 忙しくさせたところ、Myaku はその関数を名指ししました。1フレームで 2048×2048 のテクスチャを4枚作ったところ、GPU に 64 MB アップロードされたと「high」の確信度で報告しました。ブラウザのウィンドウをほかのウィンドウの後ろに隠したところ、秒間2フレームをゲームのせいにするのではなく、ブラウザがスロットリングしていると伝えてきました。
エンジンがループを握っている場合、遅いコールバックはエンジンのステップ関数になるので、原因としてはエンジンのファイルが挙がります。スパンを使えば、その中を覗けます。
profiler.span("physics", () => world.step(dt));これで判定は「Spans: physics 22 ms, render 6.0 ms」のようになり、レポートには各システムの1フレームあたりの平均コストが表示されます。
ツールとエージェントのために
Myaku が知っていることは、すべてただの JSON です。profiler.report() は、フレーム時間のパーセンタイル(平均はカクつきを隠すので p50、p95、p99)、1分あたりのヒッチ回数、原因、説明つきの最悪のヒッチ、そしてスパンを返します。window.__MYAKU__ として公開されているので、スクリプトでのプレイスルーのあとに Playwright から読めます。
debuff のプロジェクトでは、debuff dev が Myaku を自動で起動し、ゲームの update と render をスパンにします。コーディングエージェントは MCP サーバーの game_profile ツールからこれを使え、explain-stutter プロンプトが判定からコードまでエージェントを案内します。
もっと大きなアイデアの一部
Myaku は、ロジックテストのフレームワークである Keiko に続く、debuff プロジェクトから生まれた2つ目の独立したツールです。どちらも同じルールに従っています。Web ゲームのスタックにある本当の問題をひとつ、きちんと解決する。どのエンジンでも動く。debuff に依存せず、それでいて debuff とは深く統合する。