采集延迟诊断与修复方案

冻结方案快照;E1 代码与 E4 留存证据;待批准。


# 采集启动、首点与停止延迟诊断及修复方案

## 结论与批准边界

本批为诊断与待批准方案,未修改产品代码、未操作设备、未生成新产品包。读取本地最新留存会话并结合当前源码确认:启动前存在大缓存同步处理,实时重型解码与控制共用事件循环,正常指标首点与停止存在被延迟的代码路径。

此前“无设备开发全部结束,只剩 E4 验收”的判断应修正为:**存在已定位、可离线修复与回归的工程缺陷,开发重新开放**。本轮留存样本来自 iOS 17.1.1,不是 iOS 26 专属问题;该样本与用户症状高度一致,但尚未由用户确认就是反馈中的那一轮。

## 匿名留存证据(E4 历史样本,并非本轮新真机复现)

[机器证据](/archive/validation/evidence/perfowl-capture-latency-audit-2026-09-08.json) 仅含别名、时长、计数与源文件哈希。原始会话保留在本地,不提交、不上传,不修改残留 Raw。

| 时间点 / 数据量 | 观察 |
| --- | ---: |
| 用户点击 → launch_requested | 19,591.089 ms |
| ready → launch_requested | 约 18.83 s |
| launch_requested → launch_acknowledged | 约 0.221 s |
| launch_acknowledged → attached | 约 6.698 s |
| 正式启动请求前处理 Raw | 59 条 / 307,571,350 bytes |
| 最终 Raw | 432,309,505 bytes;90 条 CoreProfile + 1 条 launch |
| sample | 0 |
| capture_stopped → 外层会话结束 | 121.326 s |
| core manifest / delivery / finalizer_progress | 均未形成 / 未观察到 |
| 结束状态 | partial;graceful_stop_timeout |

时长使用 monotonicNs 差值除以 1,000,000 得到 ms;末项只有墙钟端点,以外层 endedAt 减 capture_stopped.timestamp 计算。机器账本保留三位小数、字节保持整数;这不是新增产品指标公式。sample=0 是记录计数为零,不表示 CPU/FPS 值为零。启动请求确认不等于用户看到首屏。

## 代码原因与证据限度(E1)

### 1. 点击路径仍需处理预热缓存

`MacApp/Sidecar/perfowl_collector_core/realtime.py` 的 `stream_candidate_session` 在 bridge.activate 取出缓存后,先执行整个 buffered_prelaunch_core 循环:recorder.append(同步 JSON 编码、写入、flush)→ launch_decoder.consume → projector.consume;完成后才 resolver.request_launch。循环中没有协作调度点。

留存记录在 ready 与 launch_requested 之间恰有 59 条、约 308 MB Raw。这定位了整体阻塞区间;编码、写盘与解码的各自占比尚无分段计时。预热 ring/queue 按 64/512 个 chunk 限额,而不是 byte 限额;本轮单 chunk 最大 11,201,280 bytes,条数有界不等于内存与延迟足够小。

### 2. 普通指标受重型源阻塞

全部 Adapter 顺序 start,全部准备结束才创建 consume task;已就绪的 Sysmontap 也等待其他 Adapter。预启动 CoreProfile 排在 started 首位,队列已有数据时 await queue.get 可立即返回;同步持久化与解码持续占用同一 asyncio 线程。

`launch_trace.py` 保存历史 records,在终点候选条件满足时 report 可排序重建历史语义;Frame Decoder 也可能扫描同一 Raw。各函数的实际占比需离线性能剖析,暂不将全部耗时归给其中一个函数。

样本六个普通 Adapter 均宣告 available,但落盘只有 CoreProfile Raw 与 launch,没有 sysmontap 和 sample,符合该调度缺口。available 是初始化成功,不等于已经产出数据。

### 3. 停止确认与收尾不是同一个阶段

stdin 线程已发出 stop_requested / capture_stopped;主 asyncio 循环仍要处理 stop_event、停止数据源、drain、逆序关闭与 manifest。部分退出 await 缺少统一总预算,同步解码也使异步 timeout 难以按墙钟生效。

Swift Supervisor 等满 120 秒才兜底终止。本样本没有 finalizer_progress、core manifest,所以没有证据将这次两分钟延迟归因于 report 算法。UI 收到 capture_stopped 就显示“正在生成报告”,掩盖“仍在关闭通道/封存 Raw”的实际步骤。

### 4. 启动时间空白有独立原因

实时 launch_trace 仅在完整 candidate 时输出,partial/missing 通常等 finalizer;本会话未到 finalizer,UI 也没收到启动结果。即使解除阻塞,商店 App 九阶段仍有归因/RAW schema 门禁;通道武装不等于九阶段完整。外部 observed-running/foreground-ready 应独立展示,不冒充九阶段 Total。

## 修复批次(待批准)

### L1:启动快路径与普通指标优先

- 点击路径只完成会话标识/控制记录并立即发出唯一启动请求;预热证据按原始时间留存,不在点击路径全量解码。
- 设备级准备前移;依赖新进程的源在确认身份后绑定。必要源 ready 后立即消费,慢可选源独立降级。
- 审核缓存寿命、字节预算与保留策略;RAW header、timebase、线程归因证据保留或明确报缺失,禁止静默丢弃因果数据来提速。
- 覆盖切换 App、取消预热、断线和再次开始,防止旧 token 与重复启动。

### L2:重型处理与控制隔离

- 保持唯一 DTX owner;独立处理进程只接收主机 Raw/文件引用,绝不持有设备 socket。
- 使用有序 writer、单消费者状态与独立解码进度;CPU 密集任务离开连接事件循环。
- 按字节/时间限制内存队列;溢出、写盘失败显式 source-loss/partial,不伪造零或保持 valid。
- 增量处理和有界乱序替代重复全量重建;验证公式等价、generation、时钟与 BEGIN/END 关系。若算法语义变化,先更新 Canonical 公式页。

### L3:停止与 Startup 状态真实可见

- 分离“停止采样 / 关闭源 / 封存 Raw / 后台解析 / 生成报告”,展示当前阶段、处理量与耗时。
- 源关闭、封存设置独立预算;故障隔离并保存 partial。后台报告不再持有设备;任务状态持久化,重启后可恢复。
- Startup 及时显示 collecting、partial、missing 和原因,外部启动观测与九阶段分别展示,不等完整最终结果才反馈。
- 未知 schema 不猜测映射,九阶段完整性和数值单列门禁。

### L4:离线压力回归、构建与公证

- 加入数百 MB 合成 Raw,不把真机内容复制进提交 Fixture;本地真实回放只生成匿名账本。
- 覆盖 Startup 开/关、深度源慢/快、冷启动/已运行、预热/绑定/采集中停止;补慢 writer、异常 worker、满队列、超时、取消测试。
- 校验无重复 launch、无跨会话混流、无假零;现有小 Fixture 通过不覆盖真实重载失败。
- 自动测试和站点构建通过后交付新包,Developer ID 签名、公证 Accepted、staple 与 Gatekeeper 均为交付门禁。
- 用户负责后续原生 UI 真机验收;设备连接不是离线修复的前提。

## 验收目标(待批准目标,非实测结果)

| 边界 | 离线测试目标 |
| --- | --- |
| 两级预热就绪后点击 → 发出 launch | 300 MB 预热负载下 P95 ≤ 500 ms;不包括设备启动耗时 |
| 首个合法普通源样本 → Wire | P95 ≤ 250 ms,压力条件单独列出 |
| 身份/必要源 ready → 首样本 | 1 秒采样配置下 ≤ 2 秒;源超时单列原因 |
| 点击停止 → UI 采样关闭反馈 | ≤ 200 ms;设备 drain 与报告另计 |
| 设备源停止与释放 | 正常目标 ≤ 5 秒;故障兜底 ≤ 10 秒并标 partial |
| 数据正确性 | 哈希/重放、公式、missing、丢失计数与 generation 不回退 |
| 九阶段 | 缺证据显示原因;具备对应证据后才展示具体数值 |

至少 20 轮,P95 使用升序第 ceil(0.95×n) 项(nearest-rank),绑定原始计时与测试环境。真实 USB/Wi-Fi、设备响应和数值准确性由 E4 另报。

## 下一阶段与整体进度

待用户批准后按 L1→L4 实施,优先让开始、首点与停止及时且可解释。64 项 Registry 合同与 iOS 26/27 E2 基线保持;实时交互门禁重新开放,九阶段、GPU data row、Thermal 稳定源与数值校准仍未关门。历史数字不回改,不再宣称只剩用户测试。