已完成2026-08-31

Research 01 · iOS

client_perf:哪些值得 Perfowl 借鉴,哪些必须重做

面向“对标 PerfDog”的 iOS 专项静态审查。重点不是判断项目能否启动,而是确认数据口径、采集链路和产品化基础是否适合作为 Perfowl 的长期底座。

15525730080/client_perf71474e7E1 + 部分 E2真机未验证

Executive conclusion

结论先行

总体判断:适合作为“技术路线样本”,不适合作为 Perfowl 直接代码基座。它已经把 iOS 设备发现、iOS 17+ tunnel、Instruments 数据、任务记录、标签对比和 Excel 报告串成一个可理解的原型;但指标口径、采样一致性、生命周期、安装可用性、安全边界和工程验证都不足以支撑 PerfDog 级产品。
111
仓库提交数
1,242
ios_tools.py 行数,职责过重
0
测试文件与 CI 工作流

建议借鉴

go-ios + py-ios-device 的组合思路、每设备长连接与缓存、按任务沉淀原始数据、时间段标签与基线对比。

建议重做

采样调度器、指标模型、tunnel 生命周期、数据存储、错误状态、API 安全、安装目录和报告统计。

审查范围与边界

  • 读取主分支完整历史与固定快照 71474e7138c500244127333770eeab918b3187ce
  • 重点审查 ios_tools.py、通用 Monitor、任务子进程、设备管理、数据读取、对比、API、依赖和打包。
  • 确认仓库中内置 go-ios v1.0.207 的 macOS 通用二进制,并检查 Git 文件模式与签名。
  • Python 3.12 静态编译通过;本机缺少 setuptools,因此 wheel 构建未形成有效证据。
  • 未连接真实 iPhone,未验证 iOS 版本兼容、采样误差、功耗开销、断连恢复和多设备并发。

Current architecture

iOS 数据链路

Web UIVue 2 + Element UI + ECharts,轮询接口
FastAPI设备、任务、结果、对比、导出
TaskHandle每个任务一个 daemon 子进程
iOS Adaptergo-ios 命令 + py-ios-device DTX
9 个 Monitor各自约 1 秒循环并写独立 CSV
ReportSQLite 元数据 + CSV + Excel

go-ios 负责

USB 设备发现、设备/应用信息、进程查询、iOS 17+ userspace tunnel、截图、电池和系统级 sysmontap 回退。

py-ios-device 负责

通过 RSD tunnel 连接 Instruments DTX;一个后台线程取 sysmontap,一个独立线程取 Graphics 数据,并写入每设备缓存。

最值得保留的思想昂贵的 Instruments 连接不是每个指标重复建立,而是每设备持有长连接、每秒更新一次缓存,CPU/内存/IO 等读取函数只读同一份最新快照。

Metric audit

iOS 指标能力与口径核对

指标当前来源当前范围判断Perfowl 决策
进程 CPUInstruments cpuUsage目标 PID可借鉴,但需明确是否按核心归一化保留原始值,同时输出标准化值和核心数
整机 CPU代码把进程 CPU 再写入 cpu_usage_all并非整机口径错误独立读取系统负载,禁止同值冒充
进程内存physFootprint目标 PID方向正确增加峰值、P95、增长斜率和内存告警
系统总内存physMemSize × 16KB整机单位需真机校验按返回属性元数据转换,建立机型/iOS 对照测试
FPSGraphics CoreAnimationFramesPerSecond屏幕/渲染管线只有瞬时 FPS补 Frame Time、Jank、Big Jank、Stutter、1% Low 和 120Hz
GPUDevice/Renderer/Tiler Utilization整机 GPU并非目标 App 独占UI 明确标注“设备级”,不写成 App GPU
线程数Instruments threadCount目标 PID主路径可用保留;失败时返回不可用,不用进程数量代替线程数
网络 IO系统 netBytesIn/Out整机累计不等于 App 流量改名为设备网络;另做目标 App 网络方案
磁盘 IO系统 diskBytesRead/Written整机累计不等于 App IO分开“设备级”和“进程级”,禁止混淆
电池go-ios batteryregistry整机有电量/温度/电流降低采样频率,增加电压/功率/符号解释与校准
截图go-ios screenshot整屏每秒执行过重默认 3–5 秒或事件触发,并记录截图与样本时间差
子进程聚合参数传入但 iOS 路径未使用README 与实现不一致MVP 不承诺;后续按进程树快照设计

优点:值得借鉴的部分

1. 技术组合现实

用 go-ios 处理跨平台设备控制与 iOS 17+ tunnel,用 py-ios-device 读取 Instruments 私有协议,覆盖面比单一库更完整。

2. 长连接与缓存

sysmontap 和 graphics 各自持续采集,业务指标读取缓存,避免每秒为 CPU、内存、网络、磁盘分别重连。

3. 动态属性协商

先查询设备支持的 process/system attributes,再取目标字段交集,面对不同 iOS 版本时比硬编码索引更稳。

4. 原型产品链路完整

任务、版本、基线、时间段标签、对比和 Excel 导出已经串通,说明用户工作流方向成立。

5. 任务隔离

每个采集任务独立子进程,单任务异常不会直接拖垮 Web 服务;作为原型隔离手段简单有效。

6. 跨平台工具寻址

按 Windows/macOS/Linux 与 CPU 架构选择 go-ios 二进制,并允许环境变量覆盖,适合作为 Perfowl 工具解析器的输入样本。

Risk register

缺点与风险

级别问题证据与影响改进方向
P0内置 go-ios 在 POSIX 不可执行四个二进制在 Git 中均为 100644;macOS 实测直接执行为 permission denied,代码只检查“文件存在”。构建期设置执行权限;启动前校验 X_OK、架构、版本、签名和哈希。
P0默认监听全网且无认证默认 0.0.0.0:8080,启动/停止/删除任务均可通过 GET 调用。默认仅监听 127.0.0.1;变更操作用 POST/DELETE;加入本地会话令牌与 CSRF 防护。
P0停止任务采用 SIGKILL任务进程及子进程直接 kill -9,无法保证 Instruments、tunnel、CSV 和状态一致关闭。控制通道 + 优雅停止 + 超时升级终止;会话、文件和数据库统一收尾。
P0错误用 0 伪装成有效数据多数采集异常返回 0,报告均值会把“采集失败”当成“性能很好”。样本必须含 status/source/age/error;缺失值为 null,统计自动排除并显示覆盖率。
P1九条独立采样循环不同步每个 Monitor 自己计时和写文件;电池、截图等慢调用会造成时间漂移,秒级整数时间掩盖抖动。一个主采样时钟生成 snapshot_id;各采集器按频率分组,并记录单调时钟和实际延迟。
P1多设备 tunnel 选错风险tunnel ls 始终取列表第一项,没有按目标 UDID 匹配。每个 UDID 独立 tunnel 状态机;连接前核对 address/rsdPort/udid。
P1tunnel 子进程可能阻塞stdout/stderr 使用 PIPE,但启动后不持续消费;输出积累可能填满管道。日志重定向到轮转文件或异步消费;独立守护器管理重启和退出。
P1采集开销过高截图和 batteryregistry 都进入约 1 秒循环;九个 CSV 每秒重复打开追加。指标分层频率;批量缓冲写入;对工具自身 CPU/内存/USB 开销做基线测试。
P1指标口径混用进程 CPU 被同时写为整机 CPU;系统网络/磁盘被报告为通用网络/磁盘;失败回退把“进程数”当“线程数”。数据模型强制 scope=device/process/display,并为每个字段保存方法与单位。
P1安装与运行目录混乱SQLite 写当前工作目录;任务、截图和报告写 Python 包目录 test_result统一用户工作区;App 资源只读,用户数据、缓存、日志分目录管理。
P1无测试、无 CI、依赖无上界未发现测试文件和 GitHub Actions;私有协议依赖只写最低版本。版本锁定、兼容矩阵、录制样本回放测试、真实设备冒烟和 nightly。
P1Python 版本声明失真声明 Python ≥3.7,但使用 list[str]| 联合类型和 asyncio.to_thread明确 Python ≥3.10,或改写兼容语法并加多版本 CI。
P2前端依赖公网 CDNVue、Element UI、Axios、ECharts 从 bootcdn/unpkg 加载,离线场景页面不可用。前端资源随产品本地打包,锁定版本和完整性。
P2版本与许可治理不足setup 为 5.0.0、FastAPI 显示 2.0.0;内置第三方二进制但仓库只见顶层 MIT License。单一版本源;生成第三方 NOTICE、SBOM、哈希清单与升级记录。

PerfDog gap

与 PerfDog 对标时仍缺什么

帧体验指标

client_perf 只有瞬时 FPS;对标目标需要 Frame Time、Jank/Big Jank、Stutter、掉帧分布、1% Low、刷新率变化和 120Hz 口径。

精度与可解释性

没有时间戳误差、采样覆盖率、自身开销和与 Xcode/PerfDog 对照结果;当前“看起来有曲线”不等于可用于回归判定。

诊断深度

缺少启动耗时、卡顿时刻关联、进程事件、系统日志、崩溃/Jetsam、调用栈或 Trace 等定位链路。

产品化能力

缺少稳定 CLI/CI 接口、多设备调度、阈值门禁、报告共享、团队数据治理、批量对比和可扩展采集插件。

Perfowl proposal

Perfowl 建议方案

原则:借“协议适配器”,不借“原型调度与数据模型”。可以参考它如何连接 go-ios 与 py-ios-device,但 Perfowl 应从统一样本模型、可验证口径和生命周期重新设计。
Device Runtime发现、配对、hotplug、iOS 版本与能力探测
Tunnel Manager每 UDID 状态机、健康检查、重连、日志
Metric Session单设备共享 sysmontap/graphics 连接
Sampler统一时钟、分频、snapshot_id、背压
Storage用户工作区、追加日志、SQLite 元数据、迁移
Analysis分位数、卡顿、阈值、对比、导出

统一样本最小字段

字段用途
snapshot_id关联同一采样周期的 CPU、内存、FPS 等指标
wall_time_ns / monotonic_ns既可展示真实时间,也可准确计算间隔
metric / value / unit数值与单位显式分离
scope / target区分 device、process、display、battery
source / method_version追踪来自 sysmontap、graphics 或 go-ios
status / age_ms / error_code过期和失败不再伪装成 0

批准后建议推进顺序

P0
技术验证:先证明数据
选 iOS 16 与 iOS 17+ 各一台,验证设备发现、tunnel、进程 CPU、physFootprint、FPS/GPU、断连恢复;与 Xcode/PerfDog 同场对照并记录误差。此阶段不做完整 UI。
P1
iOS MVP:统一采样与任务数据
完成设备状态机、统一样本、CPU/内存/FPS/GPU/电池/截图、用户工作区、任务开始停止、基础 HTML 报告。
P2
对标能力:帧体验与回归
增加 Frame Time、Jank、Big Jank、1% Low、标签、基线、阈值、覆盖率和版本对比。
P3
产品化:多设备与 CI
CLI、批量调度、报告归档、插件接口、升级与第三方依赖治理。
本轮待决策是否批准进入 P0 技术验证方案设计。当前报告没有修改 Perfowl 产品代码,也没有启动开发。

来源与证据

  1. client_perf 固定代码快照 71474e7
  2. Instruments session、缓存与重连实现
  3. iOS 指标函数与 Monitor 装配
  4. 通用 Monitor 一秒采样与 CSV 写入
  5. 任务子进程和 SIGKILL 停止方式
  6. 任务变更接口
  7. go-ios 官方仓库与 iOS 17+ tunnel 说明
  8. py-ios-device 官方能力与 iOS 17 tunnel 示例
  9. PerfDog 官方能力概览
  10. PerfDog Service 官方示例:指标、自动化和多设备接口