外观
三底座能力评估与架构调整草案
结论先行
Perfowl 不应把 pymobiledevice3、py-ios-device、go-ios 三套完整运行时直接串在一条 Session 中。三者都在不同程度上实现了 Apple 的设备服务或 DVT / DTX 私有协议;如果各自发现设备、创建隧道、建立 DTX 连接并读取同一事件流,反而会产生生命周期冲突、重复数据、目标进程错绑和连接争用。
推荐方案是把当前“一个 Collector 同时负责连接、隧道、采集、计算”的结构拆成两层可替换 Provider:
- Connection Broker:统一设备发现、Developer Mode / Developer image 预检、隧道租约、RSD 地址分发和断线恢复;
- Collector Provider SPI:同一 Session 只启用一个主 DTX Owner,各 Provider 输出统一的 raw event,由 Perfowl 自己完成身份绑定、公式、质量语义和归一化。
三项目的推荐定位不是“三选一”,而是:
- pymobiledevice3:近期继续作为设备控制和基础 DVT 主 Provider,但必须先评估从当前
4.21.3升级到冻结上游v11.3.1; - go-ios:作为可选 Tunnel Provider,先与 pymobiledevice3 的 macOS native / userspace 路径做同机 A/B,过门槛后才能成为某些 iOS 路由的默认实现;
- py-ios-device:作为性能协议研究 Provider,优先验证 CoreProfile 逐帧、进程网络、Energy、App Launch Lifecycle 和 GPU Counter;不直接采用其格式化结果、首点
0或硬编码算法; - xctrace:继续作为可选诊断与校准老师,不进入每次实时采集的硬依赖。
这份结论是 E1 静态证据。三个 Provider 尚未在 Perfowl 的同一台 Mac、同一台设备、同一根线、同一工作负载下完成量化对比,所以“py-ios-device 更准确”和“go-ios 隧道一定更快”目前都只能作为待验证假设。
冻结研究基线
| 项目 | 冻结提交 | 版本 / 日期 | License | 本轮证据 |
|---|---|---|---|---|
| pymobiledevice3 | e0dc322f4a0fa293353f8c13765516fbf15b1caa | v11.3.1 · 2026-09-02 | GPL-3.0-or-later | 源码、文档、测试结构 E1 |
| py-ios-device | 67b36f0c526e5bcf1d697f700df232af1bce0943 | 2.4.26 · 2026-07-06 | GPL-3.0 | 源码、README、测试结构 E1 |
| go-ios | ced7e53d94a255ee064f9773a43fceaad03c546c | 2026-08-27 | MIT | 源码、README、测试与 E2E 配置 E1 |
测试文件数量只反映仓库工程结构,不等于目标版本真机兼容证明:冻结快照中 pymobiledevice3 有 77 个 test_*.py,go-ios 有 130 个 *_test.go,py-ios-device 的 tests/ 下只有 1 个真机型 pytest 文件。go-ios 另有 macOS / Linux 自托管真机工作流;这些仍不是 Perfowl 自己的 E4。
三项目能力评估
pymobiledevice3:设备基座最完整,Perfowl 当前承接的是旧实现
优势
- 设备发现、Lockdown、应用目录、Developer image、RemoteXPC / RSD 与 DVT 服务覆盖完整;
- 当前上游 DVT API 已公开 Sysmontap、Graphics、NetworkMonitor、EnergyMonitor、ActivityTrace、CoreProfile、Notifications、Screenshot 等入口;
- 上游 iOS 17.4+ 在 macOS 上优先复用 Apple
remotednative tunnel,支持无 root;失败时再回退 userspace / tunneld; - 对 Python 3.9–3.15 与 macOS / Linux / Windows 有较完整的设备外 CI 矩阵。
对 Perfowl 的现实问题
- Perfowl 当前打包的是
4.21.3,不是本轮评估的v11.3.1;现有 Collector 依赖旧同步RemoteServer并自行维护DVTEventPump,新版已转向 asyncDvtProvider,不是一次无风险的小版本升级; DeviceConnectionService当前启动tunneld时显式写死--protocol quic。上游明确提示 iOS 18.2+ 已移除 RemotePairing QUIC,需要 TCP;路由必须改成能力协商并记录实际结果,不能继续写死;- 当前只承接了 Sysmontap、Graphics、NetworkMonitor 和 Screenshot 的一部分字段。“Perfowl 指标不足”很大一部分是承接与校准不足,并不等价于上游没有相关服务;
- GPL-3.0-or-later 的商业分发门禁仍未关闭。
判断
pymobiledevice3 仍是当前风险最低的主 Provider,但要把“旧版固定依赖”改成“版本冻结 + 适配层 + 可回滚升级”。升级前不应继续围绕 4.21.3 扩大自定义 DTX 补丁面积。
py-ios-device:指标专项价值最高,工程与算法风险也最高
优势
- 在 Sysmontap / Graphics 之外,已有 CoreProfile KDebug、进程级
NetworkStatistics、Energy debug gauge、GPU Counter、App Launch Lifecycle 的调用和解析样例; - README 与实现给出了 60 / 120 FPS、Jank、BigJank、Stutter 的完整候选链路,特别适合作为 P3 / P5 / P6 的协议研究样本;
- iOS 17 可接收外部 RSD 地址与 userspace proxy 端口,因此可以复用 go-ios 或其他 Tunnel Provider,而不必自己创建隧道。
关键风险
- README 明确写明 iOS 17 “Command line is not supported”,示例依赖外部 pymobiledevice3 / go-ios 隧道;它不是完整的现代连接底座;
- 逐帧实现依赖 CoreProfile KDebug 事件码和配置常量,跨 iOS / SoC 漂移风险高;部分入口先写死
mach_time_factor = 125 / 3再尝试由设备覆盖; - Jank 候选使用“当前帧大于前三帧均值 2 倍且大于 2 × 1/24s”,BigJank 再使用 3 倍阈值;这与 Perfowl 已归档的 PerfDog 口径并非逐项等价,不能直接复用输出;
appmonitor对 iOS 14 以下 CPU 有固定乘 40 分支,部分缺值直接转换为0;这些都违反 Perfowl 的 raw-first 与 missing 语义;- 应用筛选最终可能由 Bundle ID 转成 executable/name,必须保留 Perfowl 已实现的 Bundle ID → PID → generation 二次核对;
- 测试与 CI 结构薄弱,GPL-3.0 也没有解决分发门禁。
判断
它的正确角色是“性能协议研究 Provider”,不是替换全部 pymobiledevice3。优先保存原始回包和事件码,先用 xctrace / PerfDog / 自有 Fixture 校准,再决定哪些解析进入正式 Provider。
go-ios:最适合做长驻隧道候选,但速度优势必须量化
优势
- MIT License、Go 单二进制、并发和 daemon 生命周期更适合独立 Tunnel Provider;
- 同时提供 kernel TUN 与 gVisor userspace tunnel;有按设备过滤、端口隔离、断线清理、失败退避和 tunnel info HTTP API;
- iOS 17.4+ 能通过
CoreDeviceProxy建立 Lockdown tunnel;源码也包含 iOS 18.2+ RemotePairing 的 TLS-PSK TCP 实现和真机 E2E; - 也实现 Sysmontap、Graphics FPS、Network、Notifications 与 Screenshot,可作为基础采集备用实现。
限制与待确认项
- README 仍要求 iOS 17+ 先启动 tunnel daemon;对 Mac 单机产品,这比新版 pymobiledevice3 的 native
remoted自动路径多一个常驻组件; - userspace 路径只适用于 CoreDeviceProxy。源码明确拒绝 iOS 17.0–17.3 的 userspace tunnel,这一段仍要 kernel TUN / 管理员权限;
- 默认 TunnelManager 的边界判断使用
version.GreaterThan(17.4.0),因此恰好 iOS 17.4.0 会落到旧 RemotePairing 分支;这是必须用真机和单测确认的边界风险,不能按17.4+文案直接外推; - “better transmission performance”来自 py-ios-device README 的项目间推荐和 go-ios 的工程设计,不是 Perfowl 同机数据;新版 pymobiledevice3 在 macOS 上的 native
remoted是 kernel-routable 路径,可能优于双方 userspace 实现。
判断
go-ios 有资格成为 Tunnel Provider 候选,尤其适合长期 daemon、多设备和明确的本地端口代理;但默认路由要由 A/B 数据决定,而不是按语言或单二进制形态决定。
能力对比矩阵
| 维度 | pymobiledevice3 v11.3.1 | py-ios-device 2.4.26 | go-ios 冻结提交 | Perfowl 推荐 |
|---|---|---|---|---|
| USBMux / Lockdown / App 列表 | 完整 | 有 | 完整 | 近期 pmd3 主;Broker 统一输出 |
| iOS 17+ RSD / tunnel | native、userspace、tunneld | 只消费外部 tunnel | kernel TUN、gVisor userspace、daemon | pmd3 与 go-ios A/B 后按版本路由 |
| Sysmontap | 有 | 有,示例丰富 | 有 | pmd3 正式;其他做回归 Oracle |
| 秒级 Graphics FPS / GPU 利用率 | 有 | 有 | FPS 有 | pmd3 正式,统一 raw schema |
| CoreProfile 逐帧 | 原始服务入口 | 有事件解析与候选公式 | 未见等价完整链 | pmd3 raw + py-ios-device Research Provider |
| 进程级网络 | NetworkMonitor 需重新确认 scope;有相关 DVT 能力 | NetworkStatistics 按 PID 示例 | Network 活动流 | py-ios-device 先做候选,身份和 scope 重校准 |
| Energy | EnergyMonitor | 按 PID debug gauge | 非主要优势 | pmd3 / py-ios-device 双源校准 |
| Metal GPU Counter | 当前 DVT 清单未见等价完整解析 | 有 schema / decoder | 未见等价完整链 | py-ios-device Research Provider |
| App Launch Lifecycle | Activity / CoreProfile 原始能力 | 有生命周期解析 | 基础通知 / 启停 | py-ios-device raw spike + xctrace 校准 |
| 工程成熟度 | CI 与测试面较完整 | 测试 / CI 薄弱 | 单测、真机 E2E、daemon 治理较强 | 正式链偏 pmd3 / go-ios,实验链隔离 py-ios-device |
| 分发许可 | GPL-3.0-or-later | GPL-3.0 | MIT | GPL 法务门禁不因多进程自动消失 |
iOS 15+ 连接路由评估
| iOS | 连接主路径 | 设备侧前置 | Provider 评价 | Perfowl 发布状态 |
|---|---|---|---|---|
| 15.x | USBMux + Lockdown +匹配 Developer image,DVT 直连 | Trust;没有 iOS 16 引入的 Developer Mode 开关 | 三者不需要 RSD tunnel;pmd3 主链足够 | 待 E4,需至少 15.7.x 真机 |
| 16.x | 同上,DVT 直连 | Trust + Developer Mode + Developer image | pmd3 当前链已在 16.6.1 有限 E4 | 仅 16.6.1 已验证,不外推全部 16.x |
| 17.0–17.3.1 | RemotePairing / RemoteXPC → RSD | Trust + Developer Mode + 个性化 Developer image + 持久 tunnel | pmd3 / go-ios 都需 privileged kernel 路径;go-ios userspace 不支持该段 | 高风险兼容档,必须单列 |
| 17.4–18.1 | CoreDeviceProxy Lockdown tunnel → RSD | Trust + Developer Mode + 个性化 Developer image | pmd3 macOS native/no-root、pmd3 userspace、go-ios userspace/kernel 均可成为候选 | A/B 后定默认;17.4.0 单独验 |
| 18.2+ | CoreDeviceProxy TCP 主路径;RemotePairing 为 TLS-PSK TCP | 同上;禁止假定 QUIC | 两项目均有现代 TCP 代码;Perfowl 当前旧版 + --protocol quic 需先解除 | 未验证,不可发布为可用 |
| 26.x | 按实际 capability 协商,不只按主版本猜测 | 同上,且需匹配最新 Developer image / Host 支持 | 单独设备池与回归矩阵 | 未验证,不从 18.x 外推 |
Apple 官方说明 Developer Mode 从 iOS 16 开始用于开发工作流;iOS 15 没有这个开关。Developer services 的具体 DVT / RSD 路由属于开源项目对 Apple 内部协议的实现,不是 Apple 承诺稳定的公共 SDK,因此上表每个版本都必须经过 Perfowl 自己的 E4。
指标对系统与硬件的要求
连接成功只说明 transport 可达,不代表每个指标都有合法值。详细用户矩阵见 iOS 15+ 连接与指标兼容矩阵。架构必须支持逐能力探测:
- Sysmontap / Graphics / Screenshot:通常不要求特定 SoC,但要求 DVT 服务可用;iOS 17+ 还依赖 RSD tunnel;
- 120Hz / 逐帧体验:逐帧事件源本身不只服务于 120Hz,但验证大于 60 FPS 必须使用 ProMotion 设备;至少同时覆盖 60Hz 与 120Hz,避免把秒级 Graphics FPS 冒充逐帧 FrameTime;
- 进程网络:要求有效 PID / generation,必须覆盖 App 重启、后台、扩展进程和多进程;未证明归属时仍标 device / candidate;
- GPU Counter:字段取决于 SoC、iOS 和设备返回的 counter schema,必须运行时枚举;禁止按机型名称硬编码;
- Energy:先保存 raw payload,确认单位、目标进程 scope 和采样窗口后再发布;
- CoreProfile / Launch Lifecycle:依赖私有 KDebug 事件与时间基,跨版本漂移风险最高;每个 OS 大版本重新校准;
- Battery Temperature / Thermal:设备级能力,字段可能缺失;缺失保持 missing,不能写成 0;
- StartupTiming:拆成“被动观察已有启动”和“用户明确选择的受控冷启动”两种模式,后者可以控制启动 / 终止但仍不修改 App。
目标架构
text
SwiftUI Mac App / Session Orchestrator
│
├── Connection Broker
│ ├── pmd3-native / pmd3-userspace / pmd3-tunneld
│ └── go-ios-kernel / go-ios-userspace
│ └── TunnelLease { deviceAlias, route, rsd, localProxy, health }
│
├── Collector Provider SPI ── 每 Session 只选一个主 DTX Owner
│ ├── Pmd3CollectorProvider(正式默认)
│ ├── PyIOSDeviceResearchProvider(实验)
│ └── XctraceCalibrationAdapter(按需、离线)
│
├── Raw Event Store
│ └── payload + provider/version + route/protocol + device capability
│
└── Normalizer / Metric Registry / Quality Gate / ReportConnection Broker 必须提供的契约
text
acquire(deviceAlias, requestedCapability) -> TunnelLease
release(leaseID)
health(leaseID) -> route / protocol / latency / lastError
capabilities(deviceAlias) -> developerMode / developerImage / rsdServices核心规则:一个设备同一时刻只有一个 tunnel owner;所有下游只消费 Broker 分配的 RSD / local proxy,不得自行再次建 tunnel。租约至少记录 transportProvider、transportProviderVersion、negotiatedRoute、negotiatedProtocol、是否需要管理员权限、RSD endpoint、创建耗时、重连代数和健康状态。
Collector Provider SPI 必须提供的契约
text
probe(capabilitySnapshot) -> supported service / field / schema
start(sessionPlan, tunnelLease, targetIdentity) -> raw event stream
stop(reason) -> bounded completion
diagnostics() -> provider health / dropped events / decode errors同一 Session 只允许一个主 DTX reader;多个 DVT channel 必须由该 Provider 内部单读取器多路分发。Provider 不返回最终 PerfDog 同名指标,只返回带 provenance 的 raw facts;公式和质量判定仍属于 Perfowl。
Session 需要新增的来源事实
当前只有 pymobiledevice3Version 不足以审计一条数据。后续 schema 至少需要:
- transport provider / version;
- collector provider / version / commit;
- requested route 与 negotiated route / protocol;
- Developer Mode / Developer image 状态;
- raw service 与字段 capability;
- target PID / generation / identity status;
- metric algorithm version;
- raw payload hash、decode error、drop count 与 reconnect generation。
调整后的开发批次
| 批次 | 目标 | 产品代码条件 | 完成门槛 |
|---|---|---|---|
| R0 · Decision | 本文、兼容矩阵、Provider ADR 定稿 | 无产品代码 | 用户批准目标架构 |
| R1 · Version Baseline | 评估 pmd3 4.21.3 → 11.3.1,冻结 async DVT 适配面 | 批准后 | 旧 / 新 raw fixture 可回放;回滚路径明确 |
| R2 · Provider SPI | 建 Connection Broker / Collector Provider 接口与假实现 | 批准后 | 默认实现不切换;现有 Session 回归不变 |
| R3 · Tunnel A/B | pmd3 native/userspace 与 go-ios userspace/kernel 对比 | 需 iOS 17+ 设备矩阵 | 建链 P50/P95、吞吐、Host CPU/RSS、30 次重连、睡眠/拔插恢复有原始记录 |
| R4 · CoreProfile Spike | py-ios-device Research Provider 只保存 raw CoreProfile | 逐帧公式已入档;不发布 Jank | 60Hz / 120Hz、多 OS raw 可重放;事件码漂移显式失败 |
| R5 · Metric Expansion | 进程网络、Energy、Lifecycle、GPU Counter 分批接入 | 每个指标先独立公式与知识页 | 与 xctrace / PerfDog / Fixture 同场校准后才升级状态 |
| R6 · Capability Router | 按 OS + service probe +硬件 capability 灰度选择 Provider | R3/R5 通过 | 每条路由有 fallback;不按版本字符串单点猜测 |
| R7 · Stability & Distribution | 8h 长稳、多设备、异常恢复、universal2、SBOM / NOTICE | 许可门禁关闭 | E4 矩阵 + 发布包验证 |
需要的真机与资料
最低验证池建议为:
- iOS 15.7.x,60Hz;
- iOS 16.x,60Hz(现有 16.6.1 可继续使用);
- iOS 17.0–17.3.1,验证 privileged RemotePairing;
- 恰好 iOS 17.4.0,验证 go-ios 边界;
- iOS 17.4–18.1,至少一台 ProMotion;
- iOS 18.2+,验证 TCP 与 QUIC 禁用;
- iOS 26.x,单独验证当前系统;
- 至少一个可控 Fixture App 与一个商店 App;商店 App 只做无侵入 attach,不获取源码级结论。
如果短期无法集齐全部设备,先完成 R1 / R2 的离线兼容层和 Fixture,默认 Provider 保持不变;R3 对应版本没有 E4 就不开放该版本的产品承诺。
批准边界
本轮只完成 E1 调研与方案。建议下一次批准范围先限定为 R1:pymobiledevice3 版本基线与升级 Spike,不同时接入三个运行时,不切换默认 Provider,也不新增未校准指标。