Research 02 · iOS Performance
Codesign4QC:一套已成形的 iOS 采集底座,但指标口径仍需先校准
对当前代码快照的性能采集链路进行静态审查,结合仓库内已有测试和双真机长会话报告,区分“可直接借鉴的工程底座”与“进入 Perfowl 前必须重做的指标与判定逻辑”。
Executive conclusion
结论先行
最值得借鉴
provider 适配、进程 generation、Schema v2 事件流、优先级背压、完整性计数、会话产物和 Probe 失败不影响基础采集。
最需要警惕
GPU 存在 0–1 与 0–100 混用迹象;规则引擎只取第一个场景;部分声明指标根本未向 sysmontap 请求。
快照、范围与证据边界
- 固定分析快照:
454dbe68ee23cfca4a31d318f6597f69f74c2ec2(2026-08-31)。当前未提交文件仅涉及.DS_Store、一个 dylib 和 P12,未覆盖本报告审查的性能源文件。 - 主审查文件:
tools/performance_collector.py、AppModel.swift、PerformanceCapturePipeline.swift、PerformanceEventRuntime.swift、PerformanceMetrics.swift、Models.swift、PerformanceScenario.swift、PerformanceProbe*.swift及报告生成链路。 - E1 本轮直接阅读当前源码、测试、Git 历史与已有报告;未修改 Codesign4QC。
- E2 仓库内记录了 Python/Swift 回归、离线工具、签名和 DMG 验证;这些是已归档结果,本轮没有为静态调研重新打包。
- 历史真机记录
stage-7a-test-report.md记录 iOS 17.0 / iOS 16.3.1 各超过 1800 秒的历史真机会话,均无 drop/gap/writer failure;原始会话目录已不在当前工作区,且没有指标对照结果,因此它既不是本轮实测,也不满足 Perfowl 对 E4“真机采集并对照”的完整定义。
Data path
性能采集架构
基础无侵入层
performance_collector.py 用 DVT sysmontap 读取目标进程,同一 DVT 连接内读取 Graphics。它按 PID 优先匹配,PID 失效后按 executable 重绑,并用 generation 隔离累计量差分。iOS 17+ provider 建链对瞬时 tunnel 错误有 4 次有界退避。
事件与数据质量层
Swift 保留 v1 样本兼容输出,同时转为 Schema v2 统一事件。默认队列容量 2048、批次 64;P0 控制事件可驱逐低优先级数据,P1 可驱逐 P2,同时记录 drop、writer failure、duplicate、out-of-order、sequence gap 和队列峰值。
可选 Probe 增强层
注入的统一 Framework 可上报 display callback、主线程 stall、生命周期、启动 marker、显式 URLSession 指标和传输自监控。HMAC + CRC + sequence/generation 保护通信;Probe 缺失或连接失败时保持 dormant,DVT 基础采集继续。
Metric audit
指标口径与成熟度
| 领域 | 当前来源 | 范围 | 成熟度 | Perfowl 决策 |
|---|---|---|---|---|
| CPU | DVT cpuUsage | 目标进程 | 主路可用;多核可超 100% | 保留原值,另给 normalized/core-count,先做 Xcode 对照 |
| 内存 | Physical Footprint / Resident / Compressed | 目标进程 | 可借鉴,主指标选择正确 | 保留 scope、source、unit、quality;比较时限定同口径 |
| FPS | CoreAnimationFramesPerSecond | 前台渲染管线 | 秒级趋势;非逐帧、非 App 独占 | 只作基础层;不将 <45 / <30 秒级样本命名为 Jank |
| GPU | Device / Renderer / Tiler Utilization | 前台渲染管线 | 单位未闭环 | 建立单一 canonical 单位,原值和归一化值分字段保存 |
| IO / 调度 | 累计值按实际间隔差分 | 目标进程 | 算法可借鉴 | 保留首样本 null、计数回退 null 和 generation 隔离 |
| 功耗 | Power Score | DVT 相对评分 | 不是瓦特/电流 | 限制在同设备同场景相对对比;后续独立设计热/能耗采集 |
| 场景与规则 | Host Marker + 场景区间 + P10/P95 | 会话分析 | 架构成形,多场景判定有缺陷 | 借鉴模型,重写规则在每个场景/每次 repetition 的展开逻辑 |
| Probe 显示回调 | CADisplayLink callback | App 回调节奏 | 边界标注正确 | 保留为诊断信号,与系统最终呈现帧、FrameTime/Jank 分开 |
| Probe 网络 | 业务显式上报 URLSession metrics | 被接入事务 | 不是全流量 | 作为 SDK 协作模式,不与无侵入网络量混称 |
优点:Perfowl 可以直接借鉴的能力
1. DVT provider 隔离
iOS 17+ tunnel 与旧系统 usbmux 只停留在 provider 选择层,上层采集器可保持统一。
2. 属性协商
先查 sysmonProcessAttributes,只请求设备支持且业务需要的字段,比固定列索引更稳。
3. 重启可观测
PID 只是瞬时身份;用 executable 重绑并增加 generation,避免累计计数跨进程污染。
4. 质量是一等数据
丢弃、写盘失败、Gap、重复、乱序和队列深度被写入会话,不用“有曲线”代替可信度。
5. 热路径有界
文件句柄长期打开、utility 队列批量写入、UI 仅留最近 120 个样本,图表用极值保留降采样。
6. 会话产物可审计
原始 collector、规范化 metric、统一 event、manifest、capability、analysis 和离线 HTML 形成明确证据链。
7. 基础/增强分层
Probe 只补充主线程、显示回调、启动和业务网络;失败时不拖垮 DVT,且报告不伪造缺失数据。
8. 离线产品化
性能 collector、pymobiledevice3 和报告资源按 arm64/x86_64 打包,HTML 渲染不依赖公网。
Risk register
缺点与需要重做的地方
| 优先级 | 问题 | 代码证据 | 影响 | Perfowl 处理 |
|---|---|---|---|---|
| P0 | GPU 单位混用 | 模型文案和默认规则按 0–100%;activeGPULoadFloor=0.05 注释按 0–1;fixture 使用 0.24,collector 测试使用 17。 | 活跃 FPS 过滤、GPU P95 规则和设备间对比可能失真。 | 先真机固定原始单位,入库时统一归一化;拒绝在 UI 层猜测。 |
| P0 | 多场景规则只检查第一个候选 | PerformanceScenarioAnalyzer.evaluate 对每条 rule 使用 candidates.first。 | 后续场景即使超阈值,也可能被第一场景的 Pass 掩盖。 | 规则明确绑定 scenario selector,逐场景逐轮次评估后再汇总。 |
| P1 | 声明指标未向 sysmontap 请求 | metric_payload 读取 memAnon、memRPrvt、memVirtualSize、machPortCount、nfiles、avgPowerScore,但 PROCESS_ATTRIBUTES 不包含它们。 | 字段永远缺失,却仍出现在 model / CSV / 指标字典中。 | 用一份 declarative metric registry 同时驱动请求、解码、完整度和展示。 |
| P1 | “核心完整度”不包 CPU | 完整度只计 Physical Footprint、Resident、Compressed、Thread Count。 | CPU 全程缺失仍可报告 core completeness 100%。 | 按用户选中指标计算 completeness,每指标独立显示 coverage / stale / error。 |
| P1 | 指标选择接口实际无效 | startPerformanceCapture(selectedMetricIDs:) 接收参数,但立即改为 PerformanceMetricID.available;UI 也固定传入全部。 | manifest 的 selected 语义与真实采集范围无法作为可信契约。 | 分开 collect-set / display-set / report-set,不用一个字段同时表达三件事。 |
| P1 | DVT 与 Probe 时钟语义未完全统一 | DVT sourceMonotonicNs 来自 Mac 侧 collector;Probe payload 包含设备 monotonic;clock_sync 计数被分析,但未见统一映射后的全局时间轴。 | 跨源关联异常时可把 USB/队列延迟误当业务间隔。 | 会话建立 host/device clock model,保留原始时钟与映射误差。 |
| P1 | 默认 Pass 阈值未与刷新率/场景绑定 | 默认规则为 CPU P95 ≤80、Active FPS P10 ≥45、GPU P95 ≤80。 | 120 Hz 、静止界面、重载动画和工具类 App 使用同一判定,Pass 不具备普遍意义。 | 规则必须携带 target FPS、display Hz、场景类型、设备级别和口径版本。 |
| P2 | 长会话报告仍会累积全部数组 | 文件按 64 KB 流式读,但随后把全部 sample 和 event 加入 Swift Array,Probe 高频会话也走同一报告路径。 | 多小时或高频增强模式下,报告生成内存随事件数增长。 | 采用流式聚合 + 窗口索引 + 按需时序,报告不默认加载全部 Probe 事件。 |
| P2 | Probe 与签名注入域紧耦合 | 增强 Framework 配置、注入、描述文件和 sidecar 管理位于签名 AppModel 主流程。 | 不利于 Perfowl 作为独立性能产品保持模式边界和发布合规。 | Perfowl Core 只定义 Probe contract;注入/签名作为可选 adapter,基础模式零依赖。 |
已有验证证明了什么
dvtTunnel 会话 1804.337 秒、1386 个 DVT 样本;iOS 16.3.1 / dvtUSB 会话 1805.471 秒、1496 个样本。两者 accepted = persisted,drop/gap/writer failure 均为 0。Perfowl adoption
对 Perfowl 的借鉴清单
| 决策 | 模块/思想 | 落地方式 |
|---|---|---|
| 直接借鉴 | iOS provider 路由、tunnel 有界恢复、同 UDID 开发者操作协调 | 抽成 DeviceRuntime / TunnelManager / DVTSession 协议,不放入巨型 ViewModel |
| 直接借鉴 | PID + executable 重绑、generation 隔离、累计量差分 | 作为 iOS 进程会话的基本契约和回归测试 |
| 直接借鉴 | Schema v2 事件头、P0/P1/P2 背压、质量计数 | 重新命名并保留 contract;加入 metric scope/unit/method-version/status/age |
| 直接借鉴 | 会话目录、append-only 原始数据、manifest/capability/analysis | 按用户工作区存储,增加 schema migration、索引和保留策略 |
| 改造后借鉴 | 场景、Marker、分位数、规则和基线 | 修复多场景展开、动态刷新率阈值、比较键和样本不足状态 |
| 改造后借鉴 | Probe 的 HMAC/CRC/队列自监控与 dormant 降级 | 作为独立增强 SDK,与无侵入模式分发布、分报告口径 |
| 不照搬 | 单个 AppModel 承担设备、tunnel、签名、采集、分析和报告 | Perfowl 从第一版就拆分 domain actor/service,UI 只订阅会话状态 |
| 不照搬 | 秒级 FPS 的低帧阈值作为 PerfDog 式流畅度 | 秒级 FPS 仅用于趋势;FrameTime/Jank/BigJank 建立独立且可验证的数据源 |
获批后的建议推进顺序
固定 iOS 16 / 17+ 真机,对 CPU、Physical Footprint、FPS、GPU 原值与 Xcode / PerfDog 做同场比较;先确定 GPU canonical unit 和采集自身开销。
实现 DeviceRuntime、TunnelManager、ProcessSession、DVTCollector、EventWriter 五个边界;只接 CPU/内存/FPS/GPU 四个已校准主指标。
落地 Marker、多场景多轮次、分位数、完整度、动态阈值、可比较键和离线 HTML 报告。
单独验证 FrameTime/Jank 数据源;Probe 仅用于主线程、启动、业务网络和引擎协作,不取代系统最终呈现口径。
代码与仓库证据
/Users/itreenewbee/工作/代码/codesign4qc/tools/performance_collector.py— provider、sysmontap、Graphics、重绑与 v1 JSONL。MacApp/Sources/Codesign4QC/PerformanceCapturePipeline.swift与PerformanceEventRuntime.swift— 兼容输出、Schema v2、背压和质量计数。PerformanceMetrics.swift、Models.swift、PerformanceScenario.swift— 指标字典、统计、场景、规则和 verdict。PerformanceProbe.swift、PerformanceProbeAnalysis.swift、tools/src/enhanced_runtime/— 增强 Framework、协议与启动/显示/主线程/网络分析。docs/performance/stage-7a-test-report.md、stage-8-test-report.md、stage-10-test-report.md— 历史真机长会话、重启重绑和 Probe 传输证据。tests/test_performance_*.py与MacApp/Tests/Codesign4QCTests/*Performance*.swift— collector、fixture、事件压力、报告和可选真机回归。