mcpField
H
hz-perfetto-debug

hz-perfetto-debug

github.com/meta-quest開発241259 回インストール5 週間前に更新
リポジトリ

hz-perfetto-debug について

metavrでPerfettoトレースを取得・分析し、Meta VRデバイスの性能問題を調べるスキルです。開発者向けに、フレーム時間、CPU/GPU、スレッド、レンダリングのボトルネック調査を案内します。

主な機能

  1. 01Perfettoトレースの取得と読み込み
  2. 02CPU・GPUフレーム時間の確認
  3. 03スレッド状態と使用率の調査
  4. 04SQLによるトレースデータの検索
  5. 05GPUカウンターと描画ステージの分析

活用シーン

  1. 01スタッターやフレーム期限超過の調査
  2. 02CPUまたはGPUのボトルネック特定
  3. 03スレッド競合と同期問題の確認
  4. 04描画パスやドローコールの負荷分析

MCP 対応

エージェントスキルであり、MCPサーバーやクライアントではありません。READMEにMCP接続の説明はありません。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/meta-quest/agentic-tools --skill hz-perfetto-debug

インストール後、Claude Code で/hz-perfetto-debugを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
analyzing-traces.md
capturing-traces.md
frame-timing.md
gpu-analysis.md
sql-queries.md

詳細

Perfetto デバッグスキル

使用するタイミング

Meta VR デバイスで VR パフォーマンスの問題を調査するときに、このスキルを使用します。

  • フレーム落ち、カクつき、またはスタッター
  • CPU または GPU のボトルネック
  • レンダーパスのオーバーヘッドと GPU 使用率
  • サーマルスロットリングとクロック周波数の変化
  • フレームタイミングのばらつきと vsync の期限超過
  • スレッド競合と同期の問題
  • ドローコール数やオーバードローの多さ

VR のフレーム時間目標

各リフレッシュレートの厳格な期限は次のとおりです。フレームが目標を超えると、コンポジターによる再投影が必要になるか、ユーザーには古いフレームが表示されます。

リフレッシュレートフレーム時間の予算備考
120 Hz8.3 msQuest 2、Quest 3、Quest 3S でサポート
90 Hz11.1 msQuest 2、Quest Pro、Quest 3、Quest 3S でサポート
72 Hz13.9 msすべての Quest デバイスでのデフォルト
60 Hz16.7 msメディアアプリのみ(Quest 2)。インタラクティブアプリは 72 Hz 以上を使用する必要があります

フレーム期限をわずか 1 ms でも超過すると、古いフレーム(再投影)が発生します。全フレームの 10%を超える古いフレームは、深刻なパフォーマンス問題を示しています。

metavr のセットアップ

Perfetto のトレース機能は metavr CLI を利用します。スタンドアロンバイナリを PATH にインストールするか(metavr-cli スキルを参照)、インストールせずに npx 経由で実行します。

metavr --version

以下の例では metavr コマンドをそのまま使用しています。npm 配布版を使用する場合は、先頭に npx -y を付けてください。トレースをキャプチャする前に、開発者モードを有効にした Meta VR デバイスを USB で接続してください。

クイックスタートのワークフロー

1. トレースをキャプチャする
# Capture a 5-second trace from the currently running VR app
metavr perf capture

# Specify duration and target app
metavr perf capture --duration 10000 --app com.example.myapp

# Enable GPU render stage tracing for detailed pass analysis
metavr perf capture --gpu-render-stage

# Enable XR runtime metrics
metavr perf capture --xr-runtime

# Custom output name
metavr perf capture -o my-session-name

--app が指定されていない場合、キャプチャ時にフォアグラウンドの VR アプリが自動検出されます。CPU スケジューリングと GPU メトリクスのトレースは、デフォルトで有効になっています。トレースは自動的にローカルマシンに取得されます。

2. 利用可能なトレースを一覧表示する
metavr perf traces

変更日時の新しい順に並べた .pftrace ファイルを返します。~/Documents、~/Downloads、現在の作業ディレクトリなど、標準のディレクトリを検索します。

3. トレースを読み込む
metavr perf load <trace-file>

分析用にトレースを読み込み、処理します。16 進数のセッション ID、ファイル名(.pftrace 拡張子の有無を問わない)、またはフルパス/相対パスを指定できます。

4. パフォーマンスの概要を取得する
metavr perf context

次の内容を含む、構造化されたパフォーマンス分析を返します。

  • CPU と GPU のフレームタイミング統計
  • スレッドごとの使用率(割合)を含む内訳
  • GPU カウンターの概要(利用可能な場合)
  • 検出されたボトルネックと推奨事項
5. SQL クエリを実行する
metavr perf query <session-id> "SELECT ts, dur, name FROM slice WHERE name LIKE '%PlayerLoop%' LIMIT 20"

読み込んだ Perfetto トレースデータベースに対して、任意の SQL を実行します。slice、thread_track、thread、process、counter、counter_track、args、sched_slice など、すべての Perfetto テーブルを利用できます。

6. スレッド状態を分析する
metavr perf thread-state <session-id> <utid>

# With time range
metavr perf thread-state <session-id> <utid> --start-ts 1000000 --end-ts 5000000000

スレッドが実行中、スリープ中、ブロック中、または CPU 待ちの状態に費やした時間を示す、スレッド状態の内訳を返します。スレッドが CPU バウンドか、I/O バウンドか、またはリソース不足で実行できない状態かを特定するのに役立ちます。

7. GPU メトリクスを取得する
metavr perf gpu-counters <session-id> --start-ts 100,200,300 --end-ts 150,250,350

GPU フレーム範囲の GPU メトリクスカウンター(平均、標準偏差、分位数)を返します。統計的な精度を確保するには、少なくとも 20 フレームが必要です。メトリクスには、テクスチャフェッチレート、シェーダー ALU の処理能力、頂点処理、フラグメントシェーディングの統計が含まれます。

詳細な分析ワークフロー

パフォーマンスを徹底的に調査するには、次の手順を順番に実行します。

ステップ 1:トレースの品質を検証する

分析の前に、トレースが使用可能であることを確認します。

  • 長さ:データが 2 秒以上あること(理想的には 3〜5 秒)
  • スライス数:有意義なトレースには数千のスライスが必要です
  • プロセスの存在:対象アプリのプロセスが存在すること
SELECT
  (MAX(ts) - MIN(ts)) / 1e9 AS duration_seconds,
  COUNT(*) AS total_slices
FROM slice

トレースのスライス数が 1000 未満、または長さが 1 秒未満の場合、有意義な分析に十分なデータが含まれていない可能性があります。metavr perf capture で新しいトレースをキャプチャしてください。

ステップ 2:対象プロセスを特定する

アプリケーションのプロセス(システムサービスではないもの)を見つけます。

SELECT upid, pid, name
FROM process
WHERE name NOT LIKE 'com.oculus%'
  AND name NOT LIKE '/system%'
  AND name NOT LIKE 'com.android%'
  AND name IS NOT NULL
ORDER BY pid

既知のアプリの場合は、パッケージ名で直接絞り込みます。

ステップ 3:ゲームエンジンを特定する

エンジン固有のマーカーを確認します。

エンジン主なマーカー
UnityPlayerLoop、UnityMain、PhaseSync、PostLateUpdate.FinishRendering
UnrealUGameEngine::Tick、FEngineLoop::Tick、RHI Thread
Native OpenXRエンジンのマーカーを伴わない xrWaitFrame、xrBeginFrame、xrEndFrame
ステップ 4:重要なスレッドを特定する

VR レンダリングに関係するスレッドを特定します。

SELECT t.utid, t.tid, t.name, p.name AS process_name
FROM thread t
JOIN process p USING(upid)
WHERE p.name = '<target-process>'
ORDER BY t.name

特定すべき重要なスレッド:

スレッド目的
メインスレッド(UnityMain / GameThread)ゲームロジック、物理演算、スクリプト
レンダースレッド(UnityGfx / RenderThread)ドローコールの送信
GPU 完了(GPU completion / RHI Thread)GPU フェンスの待機
ワーカースレッド(Job.Worker / TaskGraph)並列ワークロード

スレッドの utid がわかったら、metavr perf thread-state <session-id> <utid> を使って、実行中/スリープ中/ブロック中の時間をすばやく確認します。

ステップ 5:フレーム境界を検出する

フレーム単位の分析を行うために、フレームの開始/終了マーカーを見つけます。

  • Unity:メインスレッド上の PlayerLoop スライスがフレーム境界を示します
  • Unreal:ゲームスレッド上の FEngineLoop::Tick スライス
  • OpenXR:xrWaitFrame から xrEndFrame までのシーケンス
ステップ 6:負荷の高い関数を分析する

フレームごとに最も多くの時間を消費する処理を見つけます。

SELECT name, COUNT(*) AS call_count, SUM(dur)/1e6 AS total_ms, AVG(dur)/1e6 AS avg_ms
FROM slice
WHERE track_id IN (
  SELECT id FROM thread_track WHERE utid = <main_thread_utid>
)
GROUP BY name
ORDER BY total_ms DESC
LIMIT 20
ステップ 7:高頻度の呼び出しを確認する

フレームごとに過剰に呼び出される関数は、バッチ処理の問題を示している可能性があります。

SELECT name, COUNT(*) AS calls
FROM slice
WHERE track_id IN (
  SELECT id FROM thread_track WHERE utid = <utid>
)
  AND dur < 100000
GROUP BY name
HAVING calls > 1000
ORDER BY calls DESC
ステップ 8:GPU のレンダーパスを分析する

詳細なレンダーパスの内訳、サーフェス分析、GPU カウンターの解釈については、GPU 分析リファレンスを参照してください。

主要な Perfetto の概念

概念説明
スライス実行時間を持つ区間(関数呼び出し、フレーム、レンダーパス)です。ts(開始時刻)、dur(継続時間)、name、track_id を持ちます。
トラックタイムライン上のレーンです。スレッドトラックには特定のスレッドのスライスが格納されます。カウンタートラックには時間経過に伴うメトリクス値が格納されます。
スレッド(utid)トレース内で一意のスレッド ID です。結合には tid ではなく utid を使います。tid は再利用されることがあるためです。
プロセス(upid)トレース内で一意のプロセス ID です。結合には pid ではなく upid を使います。
タイムスタンプすべてのタイムスタンプはナノ秒単位です。ミリ秒にするには 1e6 で、秒にするには 1e9 で割ります。
カウンター時系列のメトリクス(GPU 使用率、クロック周波数、温度)です。counter テーブルに格納されます。
引数スライスに付加されたキーと値のメタデータです。arg_set_id をキーに args テーブルと結合して取得します。

パフォーマンス目標

メトリクス目標警告重大
フレーム時間(90 Hz)< 11.1 ms> 11.1 ms> 16.7 ms
古いフレームの割合< 5%> 10%> 25%
メインスレッドの使用率予算の < 80%> 80%> 95%
GPU 使用率予算の < 85%> 85%> 95%
フレームのばらつき(標準偏差)< 1 ms> 2 ms> 4 ms
フレームあたりのドローコール数< 100> 200> 500

エンジン固有の注意事項

Unity
  • PhaseSync:VR の垂直同期を調整する仕組みです。PlayerLoop の開始時にアイドル時間として表示されます。これは正常かつ意図的な動作であり、無駄な時間としてフラグを付けないでください。
  • シングルパス・マルチビュー:両目を 1 回のパスでレンダリングします。1 フレームあたり 2 つのレンダーパスが見られる場合、アプリがマルチパスレンダリングを使用している可能性があります(効率が低下します)。
  • 動的バッチ処理:SetPass の呼び出し回数が多い場合は、マテリアルがバッチ処理されていないことを示すため、確認してください。
  • IL2CPP と Mono:IL2CPP ビルドでは、トレース内の関数名が異なります。C# のメソッド名ではなく、マングルされた C++ 名を探してください。
Unreal Engine
  • RHI スレッド:Unreal は、GPU コマンドを送信するために専用の RHI(Render Hardware Interface)スレッドを使用します。ドライバーのオーバーヘッドを調べるには、このスレッドを確認してください。
  • フォワードレンダリングとディファードレンダリング:Meta VR ではフォワードレンダリングが推奨されます。ディファードレンダリングは GPU コストが大幅に高くなります。
  • Blueprint の Tick:Blueprint を多用すると、UObject::ProcessEvent に現れます。件数が多い場合は、Blueprint を C++ に変換する必要があります。
  • ネイティブ化された Blueprint:トレース名に __StaticExec という接尾辞が付いて現れます。

よくある落とし穴

  • PhaseSync や xrWaitFrame のアイドル時間をパフォーマンスの問題として報告しないでください。これらは意図的なフレームペーシングの仕組みです。
  • surface#0 のような GPU レンダーパス名は内容を示すものではありません。レンダリング対象を特定するには、解像度と MSAA レベルを照合してください。
  • トレースではスレッド名が途中で切り詰められる場合があります。UnityMain が UnityMai などと表示されることがあります。
  • SQL クエリでスレッド関連のテーブルを結合する際は、必ず tid ではなく utid を使用してください。
  • タイムスタンプの単位はナノ秒です。マイクロ秒として扱ってしまうのはよくある間違いです。
  • カウンター値は瞬時のサンプル値であり、一定期間の平均値ではありません。

参考資料

各トピックの詳細なガイドについては、以下を参照してください。

コメント