第二阶段已完成2026-09-02

Implementation Result · Phase 2

Perfowl Mac 第二阶段:本地性能采集基座

在第一阶段设备与 App 选择链上,完成长驻 Collector、目标进程绑定、append-only Session、基础实时曲线与开始/停止交互。当前所有性能指标继续标记为 Experimental;代码测试、Fixture UI、打包产物和真机观测分别记录,不用任何一层替代另一层。

Collector v0.219 项 Swift 测试4 项 Python 测试真机只读冒烟指标未校准无侵入

Delivered scope

批准范围与交付结果

批准项实现状态
性能采集 SidecarPython/PyInstaller 长驻进程,协议 perfowl.collector/1,sysmontap + Graphics,stdin stop/ping已实现
目标进程绑定以 executable/PID 绑定,generation 记录重绑,App 退出后进入等待已实现
本地 Sessionsession-plan、manifest、metric-registry、capabilities、quality、Raw/Event JSONL已实现
基础实时曲线FPS、App CPU、Physical Footprint 三条共享时间轴曲线,当前值与样本数已实现
开始/停止交互采集中锁定设备/App,状态覆盖 preparing/waiting/collecting/stopping/completed/failed已实现
本地提交代码、测试、HTML、设计 Spec 与证据完成后建立窄范围提交本页收尾后执行

Foundation chain

底层链路与模块边界

DeviceFoundation → 已选 Device / User App │ ▼ PerformanceSessionController → PerformanceSessionPlan │ │ ├─ CollectorSupervisor ───┼─ perfowl.collector/1 NDJSON │ └─ handshake timeout / stop / crash │ ├─ TargetBinding ─────────── executable / PID / generation │ ├─ PerformanceSessionStore ─ raw + normalized events + quality │ └─ SwiftUI ───────────────── FPS / CPU / Footprint live curves

从 Codesign4QC 借鉴

  • DVT sysmontap 与 Graphics 的窄采集思想。
  • iOS 16 Lockdown、iOS 17+ tunneld provider 分层。
  • 按 executable 重绑和 generation 语义。
  • 只请求需要的进程属性,减少跨进程数据量。

Perfowl 自有边界

  • 版本化、带 Session/source/sequence 的协议。
  • 独立 Supervisor、10 秒握手超时和异常收尾。
  • 自有 Metric Registry、Session Schema 与质量计数。
  • 不复制签名、注入、Probe、大型 AppModel 和原产品 UI。

Collector protocol

版本化事件与目标绑定

Sidecar stdout 只输出 NDJSON,stderr 只保留诊断。宿主拒绝未知协议与 Session ID 漂移,分帧器限制单行最大 1 MB。Sidecar 启动后 10 秒没有 hello 会被 Supervisor 终止,避免界面永久停留在准备状态。

事件用途宿主行为
hello / provider / capabilities协议、版本、架构、pymobiledevice3、路由与 Graphics 能力写入 capabilities.json
ready / waiting采集服务就绪,等待目标进程出现显示等待状态
attached目标 PID 及 generation 变化更新 TargetBinding
sample进程指标和前台设备 Graphics 指标落盘并推送实时曲线
app_exited / stopped / error目标生命周期、正常结束或失败完成或失败收尾 manifest

Local session

可恢复、可追溯的 Session 包

Normalized Event 与 Raw Collector 行均采用 append-only JSONL;manifest 和 quality 在 finalize 时原子更新。客户端重启会把遗留的 recording/stopping Session 标记为 interrupted,不把半成品伪装成 completed。

SESSION_ID/ ├── session-plan.json ├── manifest.json ├── metric-registry.json ├── capabilities.json ├── quality.json ├── raw/collector-000001.jsonl └── events/events-000001.jsonl

质量快照记录 wireRecord、sample、sequence gap、duplicate、out-of-order、parse failure 和 writer failure。Metric Registry 当前定义 scope/source/unit/definitionVersion,并把未校准指标统一标为 Experimental。

Fixture UI evidence

Mac App 第一版性能工作台

使用可重复 Fixture 驱动完整链路:设备/App 选择 → 开始测试 → Sidecar 绑定 → 40 个样本 → Session completed。截图是在完成时间轴适配前保存的第一版运行证据;其曲线是 Fixture 数据,只证明 UI、状态机与落盘链能够工作,不代表真机指标准确性。随后加入的动态时间轴已由 Swift 测试与构建覆盖,仍待下一次可控窗口截图刷新。

Perfowl 第二阶段 Fixture 完成态,展示 FPS、App CPU 与 Physical Footprint 三条曲线

Fixture Session:state=completed,sampleCount=40,wireRecordCount=46,parse/sequence/writer failure 均为 0。截图刻意保留 Experimental 标记。

Real-device evidence

当前 USB 设备只读冒烟

在当前连接的 iPhone14,5 / iOS 16.6.1 上,打包 Sidecar 通过 usbmux-lockdown 建立 DVT,实际走通 hello → provider → ready → capabilities → attached → sample → stopped。稳定系统诊断目标连续取得 40 个样本,覆盖进程 CPU、Physical Footprint、Resident Memory、线程、速率计数器与前台 Graphics,并通过 stdin 正常停止。

验收对象观测结果证据边界
打包完整性首次真机建链暴露缺失 IPython.testing;修正 PyInstaller 排除项并重建后通过真实问题与修复,不是 Fixture
User App 目标完成 attached + 1 sample,随后因后台/挂起进入 waiting只证明单次绑定/读取,不是连续 App 验收
稳定诊断目标generation=1,连续 40 samples,graceful stop证明传输与连续采集;系统目标不等同产品 User App
指标准确性未执行 Xcode/PerfDog 同场对照仍为 Experimental

已将去标识摘要保存为 real-device-smoke-summary.json;不包含设备标识、设备名、App 名或 Bundle ID。

Verification ledger

验证结果按证据层分开记录

层级检查结果不能替代
Python 测试协议输出、PID/executable 匹配、指标 scope、计数器重置4/4 通过真机 provider
Swift 测试设备基座、NDJSON、协议拒绝、握手超时、提前退出、Supervisor、TargetBinding、Session/恢复、完整 Fixture 链19/19 通过真实 App 连续采集
Fixture Session40 samples,completed,Raw/Event/manifest/quality/capabilities 完整通过真机指标
Fixture UI开始、状态、三条曲线、当前值、样本数与完成态通过真机曲线
真机 SidecariOS 16 USB Lockdown、DVT、sysmontap、Graphics、40 连续诊断样本、停止只读冒烟通过App 前台稳定与指标校准
Release AppSwift release、双 sidecar/runtime、Info.plist、ad-hoc 签名与严格校验通过Developer ID/公证/通用架构

Known limits

当前明确未完成

  • CPU、Memory、FPS、GPU 与 PerfDog/Xcode 的同场误差门槛和 Metric ADR。
  • 真实前台 User App 的 10–30 秒连续客户端曲线验收;本次目标处于后台/挂起。
  • iOS 17+ tunneld 真机、设备断连、App 重启 generation 和 60 分钟稳定性。
  • Marker/场景、暂停/继续、本地历史、Session 回放、区间选择与导出。
  • xctrace 增强、上传、后端 Run、Web 报告、Developer ID、公证与 universal2。
  • pymobiledevice3 GPL-3.0 正式随包交付审查。

Next phase

建议下一批按 M1 剩余闭环推进

  1. 让测试 App 保持前台,完成真实 User App 10–30 秒、退出、重启和 generation 重绑验收。
  2. 补 Marker/场景、暂停/继续、Session 历史列表与回放,让本地测试真正可复查。
  3. 执行断线、休眠、Sidecar crash、磁盘异常和 60 分钟稳定性矩阵。
  4. 用已签名 Fixture、Xcode/xctrace 与 PerfDog 做同场校准,逐项把 Experimental 提升为 Validated。
  5. 本地闭环稳定后,再提交 M2 断点上传、Cloud Run 和 Web 单报告的详细开发计划。
下一批仍单独批准。
本阶段只交付本地采集骨架和基础实时曲线,没有启动 Marker/历史、云端、Web 或 xctrace 开发。