Research 01 · iOS
client_perf:哪些值得 Perfowl 借鉴,哪些必须重做
面向“对标 PerfDog”的 iOS 专项静态审查。重点不是判断项目能否启动,而是确认数据口径、采集链路和产品化基础是否适合作为 Perfowl 的长期底座。
Executive conclusion
结论先行
ios_tools.py 行数,职责过重建议借鉴
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 数据链路
go-ios 负责
USB 设备发现、设备/应用信息、进程查询、iOS 17+ userspace tunnel、截图、电池和系统级 sysmontap 回退。
py-ios-device 负责
通过 RSD tunnel 连接 Instruments DTX;一个后台线程取 sysmontap,一个独立线程取 Graphics 数据,并写入每设备缓存。
Metric audit
iOS 指标能力与口径核对
| 指标 | 当前来源 | 当前范围 | 判断 | Perfowl 决策 |
|---|---|---|---|---|
| 进程 CPU | Instruments cpuUsage | 目标 PID | 可借鉴,但需明确是否按核心归一化 | 保留原始值,同时输出标准化值和核心数 |
| 整机 CPU | 代码把进程 CPU 再写入 cpu_usage_all | 并非整机 | 口径错误 | 独立读取系统负载,禁止同值冒充 |
| 进程内存 | physFootprint | 目标 PID | 方向正确 | 增加峰值、P95、增长斜率和内存告警 |
| 系统总内存 | physMemSize × 16KB | 整机 | 单位需真机校验 | 按返回属性元数据转换,建立机型/iOS 对照测试 |
| FPS | Graphics CoreAnimationFramesPerSecond | 屏幕/渲染管线 | 只有瞬时 FPS | 补 Frame Time、Jank、Big Jank、Stutter、1% Low 和 120Hz |
| GPU | Device/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。 |
| P1 | tunnel 子进程可能阻塞 | 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。 |
| P1 | Python 版本声明失真 | 声明 Python ≥3.7,但使用 list[str]、| 联合类型和 asyncio.to_thread。 | 明确 Python ≥3.10,或改写兼容语法并加多版本 CI。 |
| P2 | 前端依赖公网 CDN | Vue、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 建议方案
统一样本最小字段
| 字段 | 用途 |
|---|---|
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 |
批准后建议推进顺序
选 iOS 16 与 iOS 17+ 各一台,验证设备发现、tunnel、进程 CPU、physFootprint、FPS/GPU、断连恢复;与 Xcode/PerfDog 同场对照并记录误差。此阶段不做完整 UI。
完成设备状态机、统一样本、CPU/内存/FPS/GPU/电池/截图、用户工作区、任务开始停止、基础 HTML 报告。
增加 Frame Time、Jank、Big Jank、1% Low、标签、基线、阈值、覆盖率和版本对比。
CLI、批量调度、报告归档、插件接口、升级与第三方依赖治理。