Skip to content

三底座能力评估与架构调整草案

结论先行

Perfowl 不应把 pymobiledevice3py-ios-devicego-ios 三套完整运行时直接串在一条 Session 中。三者都在不同程度上实现了 Apple 的设备服务或 DVT / DTX 私有协议;如果各自发现设备、创建隧道、建立 DTX 连接并读取同一事件流,反而会产生生命周期冲突、重复数据、目标进程错绑和连接争用。

推荐方案是把当前“一个 Collector 同时负责连接、隧道、采集、计算”的结构拆成两层可替换 Provider:

  1. Connection Broker:统一设备发现、Developer Mode / Developer image 预检、隧道租约、RSD 地址分发和断线恢复;
  2. 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本轮证据
pymobiledevice3e0dc322f4a0fa293353f8c13765516fbf15b1caav11.3.1 · 2026-09-02GPL-3.0-or-later源码、文档、测试结构 E1
py-ios-device67b36f0c526e5bcf1d697f700df232af1bce09432.4.26 · 2026-07-06GPL-3.0源码、README、测试结构 E1
go-iosced7e53d94a255ee064f9773a43fceaad03c546c2026-08-27MIT源码、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 remoted native tunnel,支持无 root;失败时再回退 userspace / tunneld;
  • 对 Python 3.9–3.15 与 macOS / Linux / Windows 有较完整的设备外 CI 矩阵。

对 Perfowl 的现实问题

  • Perfowl 当前打包的是 4.21.3,不是本轮评估的 v11.3.1;现有 Collector 依赖旧同步 RemoteServer 并自行维护 DVTEventPump,新版已转向 async DvtProvider,不是一次无风险的小版本升级;
  • 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.1py-ios-device 2.4.26go-ios 冻结提交Perfowl 推荐
USBMux / Lockdown / App 列表完整完整近期 pmd3 主;Broker 统一输出
iOS 17+ RSD / tunnelnative、userspace、tunneld只消费外部 tunnelkernel TUN、gVisor userspace、daemonpmd3 与 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 重校准
EnergyEnergyMonitor按 PID debug gauge非主要优势pmd3 / py-ios-device 双源校准
Metal GPU Counter当前 DVT 清单未见等价完整解析有 schema / decoder未见等价完整链py-ios-device Research Provider
App Launch LifecycleActivity / CoreProfile 原始能力有生命周期解析基础通知 / 启停py-ios-device raw spike + xctrace 校准
工程成熟度CI 与测试面较完整测试 / CI 薄弱单测、真机 E2E、daemon 治理较强正式链偏 pmd3 / go-ios,实验链隔离 py-ios-device
分发许可GPL-3.0-or-laterGPL-3.0MITGPL 法务门禁不因多进程自动消失

iOS 15+ 连接路由评估

iOS连接主路径设备侧前置Provider 评价Perfowl 发布状态
15.xUSBMux + Lockdown +匹配 Developer image,DVT 直连Trust;没有 iOS 16 引入的 Developer Mode 开关三者不需要 RSD tunnel;pmd3 主链足够待 E4,需至少 15.7.x 真机
16.x同上,DVT 直连Trust + Developer Mode + Developer imagepmd3 当前链已在 16.6.1 有限 E4仅 16.6.1 已验证,不外推全部 16.x
17.0–17.3.1RemotePairing / RemoteXPC → RSDTrust + Developer Mode + 个性化 Developer image + 持久 tunnelpmd3 / go-ios 都需 privileged kernel 路径;go-ios userspace 不支持该段高风险兼容档,必须单列
17.4–18.1CoreDeviceProxy Lockdown tunnel → RSDTrust + Developer Mode + 个性化 Developer imagepmd3 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 / Report

Connection 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。租约至少记录 transportProvidertransportProviderVersionnegotiatedRoutenegotiatedProtocol、是否需要管理员权限、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/Bpmd3 native/userspace 与 go-ios userspace/kernel 对比需 iOS 17+ 设备矩阵建链 P50/P95、吞吐、Host CPU/RSS、30 次重连、睡眠/拔插恢复有原始记录
R4 · CoreProfile Spikepy-ios-device Research Provider 只保存 raw CoreProfile逐帧公式已入档;不发布 Jank60Hz / 120Hz、多 OS raw 可重放;事件码漂移显式失败
R5 · Metric Expansion进程网络、Energy、Lifecycle、GPU Counter 分批接入每个指标先独立公式与知识页与 xctrace / PerfDog / Fixture 同场校准后才升级状态
R6 · Capability Router按 OS + service probe +硬件 capability 灰度选择 ProviderR3/R5 通过每条路由有 fallback;不按版本字符串单点猜测
R7 · Stability & Distribution8h 长稳、多设备、异常恢复、universal2、SBOM / NOTICE许可门禁关闭E4 矩阵 + 发布包验证

需要的真机与资料

最低验证池建议为:

  1. iOS 15.7.x,60Hz;
  2. iOS 16.x,60Hz(现有 16.6.1 可继续使用);
  3. iOS 17.0–17.3.1,验证 privileged RemotePairing;
  4. 恰好 iOS 17.4.0,验证 go-ios 边界;
  5. iOS 17.4–18.1,至少一台 ProMotion;
  6. iOS 18.2+,验证 TCP 与 QUIC 禁用;
  7. iOS 26.x,单独验证当前系统;
  8. 至少一个可控 Fixture App 与一个商店 App;商店 App 只做无侵入 attach,不获取源码级结论。

如果短期无法集齐全部设备,先完成 R1 / R2 的离线兼容层和 Fixture,默认 Provider 保持不变;R3 对应版本没有 E4 就不开放该版本的产品承诺。

批准边界

本轮只完成 E1 调研与方案。建议下一次批准范围先限定为 R1:pymobiledevice3 版本基线与升级 Spike,不同时接入三个运行时,不切换默认 Provider,也不新增未校准指标。

一手来源

Perfowl · Performance Observer