hz-perfetto-debug
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePerfetto Debug Skill
Perfetto调试技能
When to Use
适用场景
Use this skill when investigating VR performance issues on Meta Quest devices:
- Frame drops, jank, or stuttering
- CPU or GPU bottlenecks
- Render pass overhead and GPU utilization
- Thermal throttling and clock frequency changes
- Frame timing variance and missed vsync deadlines
- Thread contention and synchronization issues
- High draw call counts or overdraw
当在Meta Quest设备上排查VR性能问题时使用本技能:
- 掉帧、卡顿或画面不流畅
- CPU或GPU瓶颈
- 渲染过程开销与GPU利用率
- 热节流与时钟频率变化
- 帧时序差异与未达到垂直同步 deadline
- 线程竞争与同步问题
- 过高的绘制调用次数或过度绘制
VR Frame Time Targets
VR帧时间目标
These are the hard deadlines for each refresh rate. If a frame exceeds its target, the compositor must reproject or the user sees a stale frame.
| Refresh Rate | Frame Time Budget | Notes |
|---|---|---|
| 120 Hz | 8.3 ms | Supported on Quest 2, Quest 3, Quest 3S |
| 90 Hz | 11.1 ms | Supported on Quest 2, Quest Pro, Quest 3, Quest 3S |
| 72 Hz | 13.9 ms | Default on all Quest devices |
| 60 Hz | 16.7 ms | Media apps only (Quest 2); interactive apps must use 72 Hz+ |
Missing a frame deadline by even 1 ms causes a stale frame (reprojection). Stale frames above 10% of total frames indicate a serious performance problem.
以下是各刷新率的硬性时限。如果帧时间超过目标,合成器必须重新投影,用户会看到画面卡顿。
| 刷新率 | 帧时间预算 | 说明 |
|---|---|---|
| 120 Hz | 8.3 ms | 支持Quest 2、Quest 3、Quest 3S |
| 90 Hz | 11.1 ms | 支持Quest 2、Quest Pro、Quest 3、Quest 3S |
| 72 Hz | 13.9 ms | 所有Quest设备的默认设置 |
| 60 Hz | 16.7 ms | 仅媒体应用支持(Quest 2);交互应用必须使用72 Hz及以上 |
即使帧时间仅超过时限1毫秒也会导致画面卡顿(重新投影)。卡顿帧占总帧数的比例超过10%表明存在严重性能问题。
metavr Setup
metavr 设置
Perfetto tracing is powered by the metavr CLI. Invoke via — no install required:
npxbash
npx -y metavr --versionExamples below use the bare command for brevity; if it is not installed globally, replace with . Connect your Quest via USB with developer mode enabled before capturing traces.
metavrmetavrnpx -y metavrPerfetto追踪由metavr CLI提供支持。通过调用——无需安装:
npxbash
npx -y metavr --version以下示例为简洁起见使用命令;若未全局安装,请将替换为。在捕获追踪前,请通过USB连接Quest设备并启用开发者模式。
metavrmetavrnpx -y metavrQuick Start Workflow
快速开始流程
1. Capture a Trace
1. 捕获追踪
bash
undefinedbash
undefinedCapture a 5-second trace from the currently running VR app
从当前运行的VR应用捕获5秒的追踪数据
metavr perf capture
metavr perf capture
Specify duration and target app
指定时长和目标应用
metavr perf capture --duration 10000 --app com.example.myapp
metavr perf capture --duration 10000 --app com.example.myapp
Enable GPU render stage tracing for detailed pass analysis
启用GPU渲染阶段追踪以进行详细过程分析
metavr perf capture --gpu-render-stage
metavr perf capture --gpu-render-stage
Enable XR runtime metrics
启用XR运行时指标
metavr perf capture --xr-runtime
metavr perf capture --xr-runtime
Custom output name
自定义输出名称
metavr perf capture -o my-session-name
The capture auto-detects the foreground VR app if `--app` is not specified. CPU scheduling and GPU metrics tracing are enabled by default. The trace is pulled to your local machine automatically.metavr perf capture -o my-session-name
若未指定`--app`,捕获会自动检测前台VR应用。默认启用CPU调度和GPU指标追踪。追踪数据会自动拉取到本地机器。2. List Available Traces
2. 列出可用的追踪数据
bash
metavr perf tracesReturns files sorted by modification time (newest first). Searches standard directories including , , and the current working directory.
.pftrace~/Documents~/Downloadsbash
metavr perf traces返回按修改时间排序(最新在前)的文件。搜索标准目录包括、和当前工作目录。
.pftrace~/Documents~/Downloads3. Load a Trace
3. 加载追踪数据
bash
metavr perf load <trace-file>Loads and processes the trace for analysis. Accepts a hex session ID, filename (with or without extension), or a full/relative path.
.pftracebash
metavr perf load <trace-file>加载并处理追踪数据以进行分析。接受十六进制会话ID、文件名(带或不带扩展名)或完整/相对路径。
.pftrace4. Get Performance Overview
4. 获取性能概览
bash
metavr perf contextReturns a structured performance analysis including:
- CPU and GPU frame timing statistics
- Thread breakdown with utilization percentages
- GPU counter summaries (if available)
- Detected bottlenecks and recommendations
bash
metavr perf context返回结构化的性能分析结果,包括:
- CPU和GPU帧时序统计
- 线程利用率百分比细分
- GPU计数器汇总(若可用)
- 检测到的瓶颈与建议
5. Run SQL Queries
5. 运行SQL查询
bash
metavr perf query <session-id> "SELECT ts, dur, name FROM slice WHERE name LIKE '%PlayerLoop%' LIMIT 20"Executes arbitrary SQL against the loaded Perfetto trace database. All Perfetto tables are available: , , , , , , , , and more.
slicethread_trackthreadprocesscountercounter_trackargssched_slicebash
metavr perf query <session-id> "SELECT ts, dur, name FROM slice WHERE name LIKE '%PlayerLoop%' LIMIT 20"对加载的Perfetto追踪数据库执行任意SQL查询。所有Perfetto表均可用:、、、、、、、等。
slicethread_trackthreadprocesscountercounter_trackargssched_slice6. Analyze Thread States
6. 分析线程状态
bash
metavr perf thread-state <session-id> <utid>bash
metavr perf thread-state <session-id> <utid>With time range
指定时间范围
metavr perf thread-state <session-id> <utid> --start-ts 1000000 --end-ts 5000000000
Returns a thread state breakdown showing how much time the thread spent running, sleeping, blocked, or waiting for CPU. Useful for identifying whether a thread is CPU-bound, I/O-bound, or starved.metavr perf thread-state <session-id> <utid> --start-ts 1000000 --end-ts 5000000000
返回线程状态细分,显示线程在运行、休眠、阻塞或等待CPU上花费的时间。有助于确定线程是CPU密集型、I/O密集型还是资源匮乏。7. Get GPU Metrics
7. 获取GPU指标
bash
metavr perf gpu-counters <session-id> --start-ts 100,200,300 --end-ts 150,250,350Returns GPU metric counters (mean, standard deviation, quantiles) for GPU frame ranges. Requires at least 20 frames for statistical accuracy. Metrics include texture fetch rates, shader ALU capacity, vertex processing, and fragment shading statistics.
bash
metavr perf gpu-counters <session-id> --start-ts 100,200,300 --end-ts 150,250,350返回GPU帧范围的GPU指标计数器(平均值、标准差、分位数)。需要至少20帧才能保证统计准确性。指标包括纹理获取率、着色器ALU容量、顶点处理和片段着色统计。
Detailed Analysis Workflow
详细分析流程
Follow these steps in order for a thorough performance investigation.
按以下步骤进行全面的性能排查。
Step 1: Validate Trace Quality
步骤1:验证追踪数据质量
Before analyzing, confirm the trace is usable:
- Duration: At least 2 seconds of data (ideally 3-5 seconds)
- Slice count: Should have thousands of slices for a meaningful trace
- Process presence: The target app process must be present
sql
SELECT
(MAX(ts) - MIN(ts)) / 1e9 AS duration_seconds,
COUNT(*) AS total_slices
FROM sliceIf the trace has fewer than 1000 slices or is under 1 second, it may not contain enough data for meaningful analysis. Capture a new trace with .
metavr perf capture在分析前,确认追踪数据可用:
- 时长:至少2秒数据(理想为3-5秒)
- 切片数量:应有数千个切片才能进行有意义的分析
- 进程存在性:必须存在目标应用进程
sql
SELECT
(MAX(ts) - MIN(ts)) / 1e9 AS duration_seconds,
COUNT(*) AS total_slices
FROM slice如果追踪数据的切片数量少于1000个或时长不足1秒,可能没有足够数据进行有意义的分析。使用重新捕获。
metavr perf captureStep 2: Identify Target Process
步骤2:识别目标进程
Find the application process (not system services):
sql
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 pidFor known apps, filter directly by package name.
找到应用进程(而非系统服务):
sql
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对于已知应用,直接按包名过滤。
Step 3: Identify Game Engine
步骤3:识别游戏引擎
Look for engine-specific markers:
| Engine | Key Markers |
|---|---|
| Unity | |
| Unreal | |
| Native OpenXR | |
查找引擎特定标记:
| 引擎 | 关键标记 |
|---|---|
| Unity | |
| Unreal | |
| Native OpenXR | |
Step 4: Find Key Threads
步骤4:识别关键线程
Identify the threads that matter for VR rendering:
sql
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.nameCritical threads to locate:
| Thread | Purpose |
|---|---|
| Main thread (UnityMain / GameThread) | Game logic, physics, scripts |
| Render thread (UnityGfx / RenderThread) | Draw call submission |
| GPU completion (GPU completion / RHI Thread) | GPU fence waiting |
| Worker threads (Job.Worker / TaskGraph) | Parallel workloads |
Once you have a thread's , use to get a quick breakdown of its running/sleeping/blocked time.
utidmetavr perf thread-state <session-id> <utid>找到对VR渲染至关重要的线程:
sql
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 fence |
| 工作线程(Job.Worker / TaskGraph) | 并行工作负载 |
获取线程的后,使用快速查看其运行/休眠/阻塞时间的细分。
utidmetavr perf thread-state <session-id> <utid>Step 5: Detect Frame Boundaries
步骤5:检测帧边界
Find frame start/end markers to segment per-frame analysis:
- Unity: slices on the main thread define frame boundaries
PlayerLoop - Unreal: slices on the game thread
FEngineLoop::Tick - OpenXR: to
xrWaitFramesequencesxrEndFrame
找到帧开始/结束标记以进行逐帧分析:
- Unity:主线程上的切片定义帧边界
PlayerLoop - Unreal:游戏线程上的切片
FEngineLoop::Tick - OpenXR:到
xrWaitFrame的序列xrEndFrame
Step 6: Analyze Expensive Functions
步骤6:分析耗时函数
Find what consumes the most time per frame:
sql
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找出每帧中消耗时间最多的函数:
sql
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 20Step 7: Check High-Frequency Calls
步骤7:检查高频调用
Functions called excessively per frame can indicate batching issues:
sql
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每帧调用次数过多的函数可能表明批处理问题:
sql
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 DESCStep 8: Analyze GPU Render Passes
步骤8:分析GPU渲染过程
See the GPU analysis reference for detailed render pass breakdown, surface analysis, and GPU counter interpretation.
查看GPU分析参考文档以获取详细的渲染过程细分、表面分析和GPU计数器解读。
Key Perfetto Concepts
Perfetto核心概念
| Concept | Description |
|---|---|
| Slice | A timed span of execution (function call, frame, render pass). Has |
| Track | A timeline lane. Thread tracks hold slices for a specific thread. Counter tracks hold metric values over time. |
| Thread (utid) | Unique thread ID within the trace. Use |
| Process (upid) | Unique process ID within the trace. Use |
| Timestamps | All timestamps are in nanoseconds. Divide by 1e6 for milliseconds, 1e9 for seconds. |
| Counter | A time-series metric (GPU utilization, clock frequency, temperature). Stored in the |
| Args | Key-value metadata attached to slices. Accessed via the |
| 概念 | 描述 |
|---|---|
| Slice | 一段有时间范围的执行过程(函数调用、帧、渲染过程)。包含 |
| Track | 时间线通道。线程通道存储特定线程的切片。计数器通道存储随时间变化的指标值。 |
| Thread (utid) | 追踪数据内的唯一线程ID。连接时使用 |
| Process (upid) | 追踪数据内的唯一进程ID。连接时使用 |
| 时间戳 | 所有时间戳均为纳秒。除以1e6转换为毫秒,除以1e9转换为秒。 |
| Counter | 时间序列指标(GPU利用率、时钟频率、温度)。存储在 |
| Args | 附加到切片的键值元数据。通过 |
Performance Targets
性能目标
| Metric | Target | Warning | Critical |
|---|---|---|---|
| Frame time (90 Hz) | < 11.1 ms | > 11.1 ms | > 16.7 ms |
| Stale frame rate | < 5% | > 10% | > 25% |
| Main thread utilization | < 80% of budget | > 80% | > 95% |
| GPU utilization | < 85% of budget | > 85% | > 95% |
| Frame variance (std dev) | < 1 ms | > 2 ms | > 4 ms |
| Draw calls per frame | < 100 | > 200 | > 500 |
| 指标 | 目标 | 警告 | 严重 |
|---|---|---|---|
| 帧时间(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 |
Engine-Specific Notes
引擎特定说明
Unity
Unity
- PhaseSync: VR vsync alignment mechanism. Appears as idle time at the start of . This is normal and intentional — do NOT flag as wasted time.
PlayerLoop - Single-pass multiview: Both eyes rendered in one pass. If you see two render passes per frame, the app may be using multi-pass rendering (less efficient).
- Dynamic batching: Watch for high call counts, which indicate materials are not being batched.
SetPass - IL2CPP vs Mono: IL2CPP builds have different function naming in traces. Look for mangled C++ names instead of C# method names.
- PhaseSync:VR垂直同步对齐机制。在开始时表现为空闲时间。这是正常且有意的——不要将其标记为浪费时间。
PlayerLoop - 单通道多视图:一次渲染过程同时渲染双眼。如果每帧看到两个渲染过程,应用可能使用了多通道渲染(效率较低)。
- 动态批处理:注意高调用次数,这表明材质未被批处理。
SetPass - IL2CPP vs Mono:IL2CPP构建在追踪数据中的函数命名不同。查找混淆的C++名称而非C#方法名。
Unreal Engine
Unreal Engine
- RHI Thread: Unreal uses a separate RHI (Render Hardware Interface) thread for GPU command submission. Check this thread for driver overhead.
- Forward vs Deferred: Forward rendering is preferred on Quest. Deferred rendering has significantly higher GPU cost.
- Blueprint Tick: Heavy Blueprint usage shows up as . High counts indicate Blueprints should be converted to C++.
UObject::ProcessEvent - Nativized Blueprints: Show up with suffix in trace names.
__StaticExec
- RHI Thread:Unreal使用单独的RHI(渲染硬件接口)线程提交GPU命令。检查此线程的驱动开销。
- 前向渲染 vs 延迟渲染:Quest设备优先使用前向渲染。延迟渲染的GPU成本显著更高。
- Blueprint Tick:大量使用Blueprint会表现为。高调用次数表明应将Blueprint转换为C++。
UObject::ProcessEvent - 原生Blueprint:在追踪名称中带有后缀。
__StaticExec
Common Pitfalls
常见误区
- Do NOT report PhaseSync or xrWaitFrame idle time as a performance problem — these are intentional frame pacing mechanisms.
- GPU render pass names like are not descriptive — correlate them with the resolution and MSAA level to identify what they render.
surface#0 - Thread names can be truncated in traces. may appear as
UnityMainor similar.UnityMai - Always use (not
utid) when joining thread-related tables in SQL queries.tid - Timestamps are nanoseconds. A common mistake is treating them as microseconds.
- Counter values are instantaneous samples, not averages over a period.
- 不要将PhaseSync或xrWaitFrame的空闲时间报告为性能问题——这些是有意的帧 pacing 机制。
- 像这样的GPU渲染过程名称不具有描述性——将其与分辨率和MSAA级别关联以确定其渲染内容。
surface#0 - 线程名称在追踪数据中可能被截断。可能显示为
UnityMain或类似名称。UnityMai - 在SQL查询中连接线程相关表时,始终使用(而非
utid)。tid - 时间戳为纳秒。常见错误是将其视为微秒。
- 计数器值是瞬时采样,而非一段时间内的平均值。
References
参考资料
For detailed guides on specific topics, see:
- Capturing Traces — How to capture Perfetto traces on Quest
- Analyzing Traces — Step-by-step trace analysis with SQL queries
- GPU Analysis — Render pass analysis, GPU counters, and metrics
- Frame Timing — VR frame markers, pacing, and compositor timing
- SQL Queries — Ready-to-use SQL queries for common analysis tasks
有关特定主题的详细指南,请参阅:
- Capturing Traces — 如何在Quest设备上捕获Perfetto追踪数据
- Analyzing Traces — 使用SQL查询进行追踪分析的分步指南
- GPU Analysis — 渲染过程分析、GPU计数器和指标
- Frame Timing — VR帧标记、pacing和合成器时序
- SQL Queries — 用于常见分析任务的即用型SQL查询