Skip to content

GPU 采集技术演进与实验:从 UI 布局到 Data Row 协议未解之谜 ​

2026-10-26 · Graphics并非“有值就已稳定” ​

9月快照中的“Graphics始终稳定”“没有专项E4”已由10月来源与五轮证据细化。Renderer、Tiler、Device分别新完整5/5正式通过,仍带candidate与无完整独立精度参考标记;Dynamic GPU Counter当前暂停,不借三个利用率通过而计入。

实验表现:来源约0.99Hz与1Hz发布相撞会缺点,startSamplingAtTimeInterval:0.5并未实际提频。显式setSamplingRate:5.0后20秒40个事件、约1.952Hz,是当前环境来源资格,而非参数等于5Hz。来源余量实验。

机制与判断:采集配置、系统实际节拍和发布频率分别核对,绑定原生不透明键/序列、目标前台与freshness;每新源最多消费一次。Apple Advanced Graphics Statistics虽取得同名Renderer值,积分窗/时钟资格不足时不能当精确参考;系统同名不证明同窗。几何/填充/取消/恢复与OFF/ON只证刺激、恢复或成本,不证独立利用率准确度。准备与参考调查。

避免方式与边界:先测真实频率再开新五轮,缺新源留空;三个字段各做独占五轮,旧attempt失败保留。GPU Counter的控制消息/schema/数据行分层验收,不能把未知整数消息猜成硬件计数值。其历史解码0是旧诊断结果,不是当前所有设备的永久能力结论。Renderer · Tiler · Device。

本节E1复盘,引用E3来源资格/E4限定场景,详见实验方法索引。

1. 当前结论先放前面 ​

  • Graphics gauge (Renderer/Tiler/Device Utilization)从项目早期至今一直是稳定可用的事实源,没有发生路线更替。
  • Dynamic GPU Counter 的控制通道(配置/启动/停止/flush)从早期就能正常工作,但解码真实数据行始终是未解决的开放问题——这不是新问题,而是一条持续被真机测试反复确认、始终无法突破的边界,当前内部编号 FTI-009。
  • Workbench 展示层(GPU Counter 专用 Panel 布局)已经修复完成,但这只解决了"UI 有地方显示数据"的问题,不代表"有数据可显示"——UI 修复与数据链路修复是两件独立的事。

2. 最初工程问题 ​

Perfowl 需要在不依赖 Xcode/开发签名的前提下,通过 pymobiledevice3 的 DTX 内核连接 Instruments 的 GPU 相关私有服务,获取图形管线负荷数据,用于卡顿归因。

3. 第一代方案与为什么当时合理 ​

第一代方案直接对接 Instruments Graphics 服务(com.apple.instruments.server.services.graphics.opengl),因为这是 pymobiledevice3 已经有原生封装(Graphics(provider))、语义相对公开(Renderer/Tiler/Device 百分比)的服务,能快速提供可用的图形利用率数据。

4. 暴露出的真实问题 ​

Graphics gauge 只能提供三个聚合百分比,无法提供更细粒度的硬件计数器信息(如具体的着色器周期、纹理带宽等)。为了追求更深入的图形诊断能力,团队尝试对接 Apple 私有的 GPU 硬件计数器服务(com.apple.instruments.server.services.gpu)——这条路线暴露出的问题比预想的更深:控制层协议相对好理解(configure/start/data/stop/flush 序列清晰),但数据层的消息格式是完全私有、未公开文档的动态 schema。

5. 候选方案:GPU Counter 控制封装 + 自研解码器(部分采纳,数据层未完成) ​

  • 假设:仿照其他 deep raw adapter 的模式,先把控制协议封装稳定(GPUCounterStream:requestDeviceGPUInfo → configureCounters(...) → startCollectingCounters → ... → stopCollectingCounters → flushRemainingData),再逐步攻克数据层解码。
  • 实验(Build60 E4 复测,2026-09-16):真机 Session 中 GPU Counter 被正确纳入 CapturePlan 后,共收到 1248 条 GPU raw event:1 条 device-info、1 条 schema-ready、其余 1246 条均为当前 decoder 不支持的 [int, int] 两整数 message shape,decoded data row = 0。
  • 判定:控制层封装成功,数据层解码未成功。团队明确冻结原则——未知的两整数消息不得被猜测性地解释为计数器数值,必须从原始 DTX dispatch/notification envelope 重新取证、核对 configureCounters:counterProfile:interval:windowLimit:tracingPID: 的参数合同后才能继续推进,不允许为了让 UI"看起来有数据"而编造解码规则。

6. 候选方案:新鲜度与显示质量门禁(已采纳,与数据层问题正交) ​

  • 假设:即使数据层尚未解决,也应该先把"展示层如何诚实处理陈旧/无效数据"的质量语义定下来,避免未来数据层修复后又要返工展示逻辑。
  • 实验(R5 GPU Counter 实时新鲜度,2026-09-10):冻结规则——实时 counter 展示采用 host receive monotonic 最近合法 data row 时间;当前 sample 时间与它差值 > 10 秒或时钟倒退,置 missing,不保持最后值无限有效;仅合法且 decode_status=decoded 的 counterValues 可更新时间;schema 变更/明确无效数据/reset 清空当前窗口;普通 heartbeat 不算数据也不延长有效期;0 是合法值。10 秒阈值来自已批准计划的初始合同,待真实协议/低频设备验证,不宣称已对所有 SoC 校准。
  • 判定:采纳,是当前 gpu.counter.raw 展示层的标准质量规则,独立于第 5 节的数据层解码问题——即使未来 decoder 解决了两整数消息问题,这套新鲜度规则仍然适用。

7. 候选方案:GPU Counter 专用 UI Panel 布局修复(已采纳) ​

  • 问题:早期 UI 曾把 GPU Counter 的展示和其他实时指标混在一起,布局不清晰。
  • 判定:采纳,Build60 已解决专用 Panel 布局问题。但真机复测同时确认,这只是"有地方展示"的修复,decoded data row 依然为 0——UI 问题的解决不代表数据问题的解决,这是本次演进中一个值得记录的教训(见第 10 节)。

8. 被证伪路线与停止条件 ​

当前 devlog 中未发现"为了让 GPU Counter 出值而猜测两整数消息含义"这类路线被尝试后又撤销的记录——团队从一开始就明确拒绝猜测,这是一条主动设立的停止条件,不是试错后才确立的。这也是与其他领域(如 Startup 的多路线试错证伪)不同的演进模式:GPU Counter 领域的核心约束更多是"证据不足时主动不动手",而不是"尝试多条路线后逐一排除"。

9. 最终方案为什么是当前状态(尚未有"最终胜出方案") ​

GPU 领域目前是双轨状态,不是单一方案胜出:

  1. Graphics gauge 轨道:已稳定,作为当前唯一可用于图形负荷分析的 GPU 事实源;
  2. Dynamic Counter 轨道:控制层稳定、数据层未解决,明确保持 candidate 状态,不允许为了产品完整度而伪造或猜测数值。

这个"诚实卡住"的状态本身就是团队工程原则的体现:宁可一个指标长期不可用,也不用猜测的数值冒充真实证据。

10. 从 POC 到产品化又踩了什么坑 ​

  • 第一轮 Session 的 gpu.counter.raw=0 一度可能被误判为 bug:实际原因是 Recording 中途才添加 GPU Counter,Start 时该指标未进入 CapturePlan,这是预期内的产品语义("采集中添加未武装数据源型指标只影响 UI/下次 Session,不动态修改当前 CapturePlan"),不是数据链路故障——第二轮从 Start 就包含该指标后才暴露出真正的 FTI-009 数据层问题。这提醒后续排查类似"无数据"问题时,要先确认指标是否从 Session 一开始就被采集,再判断是否是真实的协议/解码问题。
  • UI 修复与数据链路修复要分开验收:Build60 的 E4 复测同时验证了两件独立的事(UI Panel 布局、GPU Counter 数据链路),结果一个通过一个不通过,说明这两类问题不能被一次验收笼统打勾。

11. 当前仍未关闭的门禁 ​

  • FTI-009:GPU Counter decoded data row 恒为 0,需要从原始 DTX dispatch/notification envelope 重新取证,核对 configureCounters 参数合同后才能推进 decoder;跨 SoC 的计数器数量、名称、单位差异尚无任何真机证据。
  • Graphics gauge 虽然稳定,但没有独立于其他指标域的专项 E4 校准批次。

12. 可复用工程经验 ​

  1. 控制层可达不代表数据层可用——这是本次演进最核心的教训,适用于任何私有协议对接场景:先分别验收"能不能连上"和"连上后有没有可信数据",不要把两者混为一谈。
  2. 未知消息格式面前,"不猜"比"能展示"更重要——团队多次在证据不足时选择保持 missing/candidate,而不是为了产品观感编造一个看起来合理的数值。
  3. 区分"指标从一开始就没被采集"和"指标被采集但解码失败"——两者表现相似(都是看起来没有数据),但排查方向完全不同,第一轮 Session 的插曲说明了这一点。

13. 原始 devlog 索引 ​

  • p5-gpu-freshness-work.md:GPU Counter 实时新鲜度门禁(R5)。
  • p3-p4-frametime-continuation-and-gpu-counter-ui-repair-plan.md:GPU Counter UI Panel 修复与 Build60 E4 复测(FTI-009 首次记录)。
  • p4-build59-screenshot-e4-followup-repair-plan.md:FTI-009 后续统一实施方案。
  • p4-fti010-missing-metrics-and-frametime-repair-plan.md:GPU Counter schema/data row 后续排查方向。

完整正文见 site/devlog/index.md 时间线或对应 /archive/ 归档页。

14. 延伸阅读 ​

版本历史补记 ​

日期修订来源
2026-10-26补本月实验结论、失败路线与适用限制;早期阶段数字保留月度梳理

Perfowl · Performance Observer