关于 quest-perf
quest-perf 是面向 Quest 开发者的 Horizon OS 应用性能诊断与优化技能。它强调依据帧预算解读采集指标,并针对已测出的瓶颈选择优化实验。
主要功能
- 01帧预算与指标解读
- 02按瓶颈选择优化方向
- 03Perfetto 和 RenderDoc 采集流程
- 04优化前后测量方法
适用场景
- 01诊断半帧率渲染
- 02为疑似瓶颈选择分析工具
- 03在真实头显上比较优化效果
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ssheleg/ xr-dev --skill quest-perf安装后在 Claude Code 中输入/quest-perf确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/capture-playbook.mdmobile-rendering.mdrendering-playbook.md详细介绍
Quest 性能:预算、误区与捕获
Horizon OS 上的性能优化有两种常见失败方式:没有捕获数据就优化,或者错误解读捕获数据。这项技能先解决第二种,因为平台上最常被引用的数字——GPU%——恰恰会在最重要的时候误导你。
对于整个产品的路线图或阶段审查,请使用 quest-lifecycle;单项技术任务仍由此技能负责。如果缺少相关信息,请在行内说明当前阶段、阶段证据和下一个前置条件。
选择渲染管线,或调查 tile、渲染通道、几何体、过度绘制和资源开销时,请阅读 references/mobile-rendering.md。
预算是截止时间,不是目标
| 刷新率 | 每帧时间 |
|---|---|
| 72 Hz | 13.9 ms |
| 90 Hz | 11.1 ms |
| 120 Hz | 8.3 ms |
CPU、渲染线程、GPU 和合成器的工作构成一条流水线,可以跨帧重叠执行。请将关键路径和同步情况与截止时间进行比较;不要把独立的 CPU/GPU 采样值相加,当作通用的帧时间公式。错过提交时可能会触发重投影,产生的可见伪影取决于运动、深度和所选运行时路径。
GPU% 的误区与 50% 阈值
应用降至半帧率时,GPU 会提前完成工作并进入空闲,因此利用率会下降,即使应用显然受 GPU 限制。
FPS=36/72 Stale=36 GPU%=0.65 App=18.05ms
FPS=36/72— 半帧率:每帧显示两次。App=18.05ms— 实际的每帧 GPU 时间,而预算为 13.9 ms。GPU%=0.65— 按加倍后的 27.8 ms 时间间隔测得,因此读数为 65%,但应用需要的是降低 23%,而不是该读数暗示的 35%“余量”。
规则:以毫秒为单位读取 App,并与刷新率预算比较。只有接近饱和时才相信 GPU%。要摆脱半帧率状态,GPU 工作必须在一个刷新间隔内完成——也就是说,半帧率时利用率必须降至约 50% 以下。
如果 App 在预算范围内,而 Stale 仍不为零,请在跟踪记录中检查 CPU 提交、同步和合成器时序。仅凭这一症状不能证明存在 CPU 瓶颈。上文的半帧率示例假设所列指标定义成立,且未启用有意设置的 SpaceWarp 模式;请先核实这两点。
根据测得的瓶颈选择优化手段
选择 multiview、渲染比例、注视点渲染、图层、资源、着色器或重投影时,请阅读 references/rendering-playbook.md。其中将每项实验与其前置条件、视觉失效情形和目标设备上的证据关联起来。
- Dynamic Resolution — 通过引擎/SDK 支持的控制路径调整渲染比例;请验证实际效果,不要假设 OS 会自动启用。
- Foveation — 区分固定注视点渲染和眼动追踪注视点渲染;测试受支持的级别和画质。简单着色器在 FFR 下的开销可能高于未启用 FFR 时。
- Refresh rate — 请求代表性工作负载能够持续支持的刷新率;观察实际运行时表现和热行为,不要承诺刷新率会自动变化。
- Application SpaceWarp — 这是需要支持深度/运动矢量集成,并进行伪影和延迟测试的方案,不是自动补救手段,也不保证能提升特定百分比。
捕获链——每种工具能回答什么
| 问题 | 工具 | 方法 |
|---|---|---|
| 是否有丢帧,以及发生在哪里 | logcat VrApi 统计数据(FPS、Stale、App、GPU%) | metavr log / adb logcat |
| 头显内的实时数据 | OVR Metrics Tool(ovrmetric APK) | metavr tools install ovrmetric,然后启用其叠加层 |
| CPU 与 GPU、线程时间线、停顿 | Perfetto | metavr MCP start_perfetto_capture → stop_perfetto_capture → analyze_trace,或使用对应的 CLI 命令 |
| 哪些 C/C++ 函数消耗了 CPU | simpleperf | 使用 Android NDK 的 simpleperf 分析正在运行的包 |
| 哪个绘制调用、着色器或渲染阶段消耗了 GPU | RenderDoc Meta 分支 | metavr tools install renderdoc;绘制调用跟踪、渲染阶段跟踪、Vulkan 着色器统计数据 |
Meta 为其中两种工具提供了任务技能——hz-perfetto-debug 和
hz-simpleperf-debug,另有用于一般设备端调试的 hz-vr-debug。安装这些技能后,
本技能负责决定测量什么,而它们负责驱动工具。
references/capture-playbook.md 包含准确的操作步骤,包括应捕获哪些内容,以便其他 Agent 能据此采取行动。
方法:确保第二次捕获有意义
- 在真实头显上的发布版本中复现问题。模拟器运行
(
xrsim、spatialsim)用于检查受支持的模拟行为,而非头显性能。 - 先记下刷新率及由此产生的预算,再查看其他内容。
- 在应用最糟糕的场景中进行捕获,而不是在菜单中。
- 每次只更改一项;重新捕获;比较
App毫秒数,而不是主观感受。 - 在项目自己的记录中记下前后数据(之前/之后的
App、Stale、场景、构建 ID)——没有捕获记录的性能声明只是看法。
会让调试多走一轮的注意事项
- 头显因温度过高而降频,会使对比失效。 长时间运行会导致状态变化;让设备冷却,或在记录数据时注明温度状态。
- 开发模式叠加层和日志记录会消耗帧时间。 先关闭它们进行测量,只有在读取无法通过其他方式获取的数据时才启用。
- 计数器的含义取决于捕获/运行时模式。 在将陈旧帧计数解读为工作丢弃或流水线延迟之前,先检查时间戳和重投影状态。
- 绘制调用消耗 CPU,填充消耗 GPU。 在受填充率限制的帧中减少绘制调用不会带来变化,因此要先进行捕获。
- WebXR 有自己的计数器——浏览器文档中的绘制调用指标;将原生应用建议用于 Web 构建之前,请参阅
quest-webxr。
帧预算、65%/18.05 ms 的演算示例及恢复机制摘自 documentation/native/android/os-missed-frames.md,日期为 2026-09-20;
请通过 metavr docs search "missed frames" 重新核实。
触发词
更多会导向此处的短语:"profile the headset" / "分析头显性能","app is hot" / "应用发热","judder" / "画面抖动","GPU bound" / "受 GPU 限制","perfetto trace" / "perfetto 跟踪","simpleperf","RenderDoc","OVR Metrics","stale frames","SpaceWarp", "foveated rendering" / "注视点渲染","72 vs 90 Hz"。