外观
标注输入卡顿与启动阶段 CPU 断档诊断
背景
Owner 2026-11-02 在内部包 237 上连续录了两场目标 App A 的会话(设备 A,iOS 26),反馈 CPU 曲线断数据,并在第二场复测后判断“点击标注后数据就断了”。同日 Owner 指定 Claude 负责全项目修改与优化(兼任 Lead 与 Implementation,见 AGENTS.md),本批诊断与修复由 Claude 决策并实施。
证据(E3,会话原件)
两场均为采集完成状态:线路序号 0 缺口、0 重复、0 乱序,两条连接无错误、无重连。断档出现在采集进程收到 sysmontap 数据的时刻上,不是电脑端丢弃。
| 会话 | 时长 | 标注保存时刻 | 整机 CPU 来源间隔 > 1.5 秒 | activitytrace 逐帧来源试探期 |
|---|---|---|---|---|
| 第一场 | ≈29 秒 | 第 16.9 秒 | 2.6 秒起 2.8 秒;5.4 秒起 1.7 秒 | 0–8.3 秒 |
| 第二场 | ≈22.5 秒 | 第 12.9 秒 | 3.3 秒起 3.1 秒;6.4 秒起 2.1 秒;8.8 秒起 2.3 秒 | 0–13.1 秒 |
| 10-30 有 3 次标注的会话 | ≈87 秒 | 33.6 / 61.3 / 81.0 秒 | 无 | 0–4.4 秒 |
| 10-30 无标注的三场 | ≈52–55 秒 | 无 | 最多一次 1.6–1.7 秒 | 0–3.6~4.1 秒 |
- 第二场所有断档都发生在标注保存之前;试探期一结束,积压的 sysmontap 数据在约 9 秒内以正常两倍速率集中补到。
- 第二场电脑端队列(Supervisor 入队→Controller 出队)在标注保存前 6 秒内出现 737 / 95 / 761 / 625 毫秒等待,其余样本约 0.2–0.6 毫秒,说明输入标注期间主线程被占用。
- 两场的帧耗时来源都没有选出(第一场
primary-insufficient-evidence,第二场resource-limited),逐帧统计只覆盖启动后约 1.2–1.6 秒。
判断
- 已证实(E3):输入标注时主线程长时间被占用。代码中标注草稿
noteText是整个工作台根视图的@State,每输入一个字(含输入法拼字)都会使 2700 余行的工作台连同实时图表全部重算;这是界面“停住”的直接原因。 - 已证实(E3):落盘数据里的 CPU 断档来自采集进程侧,与启动/逐帧追踪试探期重合;标注本身不写入采集进程,10-30 的三次标注都没有引起断档。
- 待证(假设):本机为 4 物理核 Intel 笔记本,启动追踪连接在会话中传输 0.2–3 GB 数据;试探期的追踪解码与界面重绘可能共同占满 CPU,使 sysmontap 读取落后。标注输入是否会加重采集侧断档,需要 A/B 复测才能定论,不写成结论。
本批实现
| 文件 | 修改 |
|---|---|
MacApp/Sources/PerfowlApp/PerfowlWorkbenchView.swift | 新增私有子视图 NoteComposer,草稿文字状态移入其中;根视图只保留弹窗开关,提交后通过闭包调用原有 appendNote 并关闭弹窗。输入、提交、空白禁用与无障碍标识均保持不变。 |
- 复杂度:每次按键的重算范围从整个工作台缩小到弹窗内一个文本框与按钮,与会话长度和图表数量无关。
- 未改采集链路、指标公式与标注落盘格式。
验证
swift build --product Perfowl通过(E2)。- 前后对比基准:以
host-queue-timing.json中输入标注期间的出队等待为指标,修复前为 625–761 毫秒;修复后需 Owner 在新包上复测(待 E3)。
遗留与下一步
- A/B 复测(Owner 操作):同一目标 App,各录约 60 秒;A 场全程不加标注,B 场在第 20 秒后(试探期结束后)打开标注框并输入约 10 秒。用于区分“启动试探期断档”与“标注输入加重断档”。
- 启动/逐帧追踪试探期挤占 sysmontap:需要另立方案,方向包括给 sysmontap 独立读取优先级、限制试探期追踪数据量,以及让报告标明逐帧统计的实际覆盖时长。
- 逐帧来源过滤未生效(请求
0x31800318,实际过滤列表为空)导致帧耗时整场缺失,单独立项。
Validation Update · 2026-11-02:内部包 238 构建与同址安装(E3)
- 来源:main
1088df14,Developer ID 签名完整构建 203.6 秒,来源门禁passed,包内提交号与 main 一致。 - 校验:App 与 DMG 严格签名;冻结核心 107 个模块与 CLI 和源码一致;DMG 挂载、安装后文件树一致;安装后核心
probeready。 - 产物:
MacApp/dist/Perfowl-238-macos-x86_64-internal.dmg,147,851,233 B,SHA-256097a96a8a5c6964dde0d6d0804a4e7469d13c5bade6bacde3d6a037db4758509;237 安装包与回滚包移至私有归档并核对可恢复。 - 启动器唯一:打包暂存目录改为
.noindex并在安装后删除;LaunchServices 与 Spotlight 只剩/Applications/Perfowl.app(首次按新规则实证)。 - 未完成:公证按 Owner 内部测试边界暂缓(Gatekeeper exit 3、stapler exit 65);标注输入卡顿修复的效果与 A/B 复测待 Owner 在 238 上完成;未跑 Swift/Python 全量回归(本批只改一个 SwiftUI 视图)。
Validation Update · 2026-11-02:238 上 A/B 复测(E4,设备 A / 目标 App A)
Owner 在 238 上连续录 3 场:
| 会话 | 时长 | 标注 | 每秒行 | 进程 CPU/整机 CPU/内存缺值行(除首行预热) | 最大行间隔 | 电脑端最大出队等待 | 逐帧试探期 | sysmontap 来源间隔 > 1.5 秒 |
|---|---|---|---|---|---|---|---|---|
| A | ≈190 秒 | 无 | 190 | 0/0/0 | 1.08 秒 | 28.2 毫秒 | 0–4.6 秒 | 0 |
| B | ≈25 秒 | 1 次 | 26 | 0/0/0 | 1.06 秒 | 60.2 毫秒 | 0–3.6 秒 | 0 |
| C | ≈66 秒 | 3 次 | 66 | 0/0/0 | 1.02 秒 | 25.2 毫秒 | 0–3.7 秒 | 0 |
- 标注期间界面出队等待从修复前的 625–761 毫秒降到最多 60 毫秒;4 次标注前后 CPU、内存逐秒连续。
- 逐帧试探期回到约 4 秒(与 10-30 一致),本轮没有出现启动阶段断档。237 两场试探期为何拉长到 8–13 秒、界面占用是否通过本机 4 核 CPU 竞争放大了采集侧断档,本轮无法单独证实,不写成结论;若再出现断档,按原件复查试探期时长与来源间隔。
- 结论:标注导致的界面卡顿与 CPU 断档在本轮真机复测中未复现,标注修复验收通过(E4,3 场、4 次标注,单设备单目标 App)。帧耗时来源未选出、帧过滤未生效仍为开放项。