外观
CPU / Sysmontap 技术演进与验证
2026-10-26 · 高频参考、来源新鲜度与1Hz交付的实验更新
本节承接10月证据;下文9月“未发现相关实验”“没有专项”的结论只代表当时审阅快照,不是当前事实。进程CPU旧验收沿用;整机Raw/Normalized和逐核在10月17–18日分别完成新专项,物理核身份与完整外部精度仍另列。
表现与原因:固定每秒刷新不证明有新的系统字段;来源停止后沿用缓存会制造假连续。共享Sysmontap的字段闭包、同Raw来源、原生窗口及目标生命必须共同核对;另一字段更新不得给旧CPU续命。G118来源修复。
被限制的参考路线:500Hz双API参考五组完整成本1.25795%–1.34210%超过原1%门,部分组漏点;该路线不能准入,不等于CPU指标不可测或产品数值已错。设备/版本/工具改变前不重刷相同失败矩阵。G132。
后续实测与边界:整机Raw正式队列曾因热保护与参考包络过宽停止,旧失败全保留;绝对deadline修复解决参考调度逐点漂移后另立完整新五轮,最终只接受受控低—中负载。Normalized另核真实显示链路,逐核只核来源数组顺序与无标签分布,不把下标当P/E物理核。Raw与调度实验 · Normalized · 逐核。
复现与避免:先做OFF/ON完整工具成本,再固定产品窗口与读取上下界;包络过宽为不可评估,不能记普通或零误差。计数器必须按新源时间差分,首点warmup 、重置断开基线;从0.5秒切到1Hz属于显式合同变更,不偷偷换分母。上下文切换1Hz专项。App CPU的单核100%多核累加与除有效核心数的容量口径分开标注;跨设备旧均值不是同场误差。App CPU。
本节复盘E1,引用历史E2/E4,不重测历史指标;完整方法见实验方法索引。
1. 当前结论先放前面
- Perfowl 全部 CPU / 线程 / 调度 / 磁盘 I/O 指标(APP CPU、TotalCPU、Per-Core、Thread Count、Context Switch Rate、Interrupt Wakeup Rate、Disk Read/Write)共享同一个事实源:pymobiledevice3 原生
Sysmontap.create()订阅的com.apple.instruments.server.services.sysmontap。这条通道从项目早期至今没有发生过路线更替,是相对稳定的基础设施,不像 Startup 领域经历过多次源切换。 - 真正的工程演进发生在公式层:从"直接展示原始字段"演进为确定性的 Raw → Metric 公式引擎(
RawMetricEngine/MetricEngine),把 gauge 与 counter 的差异、fail-closed 的核数归一化、counter-reset 语义显式固化下来。 - 当前证据等级是内部自校准(formula self-calibration):证明 Perfowl 自己的 raw→metric 公式、单位、scope、质量语义内部一致,不是与 PerfDog 等第三方工具的同窗对照校准(该项目按用户决定明确标记为
not-tested)。
2. 最初工程问题
sysmontap 是 Instruments 传统上用于展示进程/系统 CPU 面板的私有 DTX 服务,pymobiledevice3 已经提供了对它的原生封装。Perfowl 需要解决的不是"能不能拿到数据",而是"拿到的原始字段该如何变成一套语义清晰、可信、能做版本回归的指标"。
3. 第一代方案:直接透传原始字段
最初版本直接读取 cpuUsage / CPU_TotalLoad / threadCount 等字段并展示,这在早期验证阶段是合理的最小实现,能快速证明链路可用。
4. 暴露出的真实问题
- gauge 与 counter 混淆:
cpuUsage、threadCount、PerCPUUsage是瞬时快照(gauge),但ctxSwitch、intWakeups、diskBytesRead/Written是累加计数器(counter),如果不加区分地直接展示,counter 字段会呈现单调上升的巨大数字而不是有意义的速率。 - 核数归一化的猜测风险:早期如果假设固定核数(如硬编码 6)做归一化,遇到不同机型会产出错误的百分比。
- 进程重启导致的计数器跳变:目标 App 崩溃重启后 PID 变化、counter 归零,如果不处理会产生巨大的负值速率或虚假尖峰。
5. 候选方案 A:统一的确定性 Raw→Metric 公式引擎(已采纳)
- 假设:把"字段是 gauge 还是 counter""如何差分""何时该 fail-closed"集中到一个可测试、可离线重算的引擎里,比在展示层零散处理更可靠。
- 实现(
CORE-8,2026-09-05):新增RawMetricEngine,只消费已落盘的perfowl.raw-event/1,输出确定性的perfowl.metric-frame/1,CLI 新增derive SESSION支持同一份 raw 数据离线重算——这意味着公式变更后可以对历史 raw 数据重新验证,而不需要重新采集。 - 判定:采纳。当前
MacApp/Sidecar/perfowl_collector_core/metric_engine.py延续这一设计,_system_metrics处理 gauge 类系统字段,_counter_rate统一处理所有 counter 类字段的差分。
6. 候选方案 B:EnabledCPUs Fail-Closed 归一化(已采纳)
- 假设:核数归一化不应该假设任何固定值,必须等到真正观测到系统上报的核数才计算。
- 实现:
_system_metrics中enabled = self._enabled_cpu_count(仅在EnabledCPUs > 0时被观测并缓存),normalized = total / enabled if total is not None and enabled is not None and enabled > 0 else None——本会话从未观测到EnabledCPUs时,ios.device.cpu.total.normalized严格保持missing。 - 判定:采纳,当前
definitionVersion为raw-dvt-divided-by-enabled-cpu-count.candidate.v2(仍是 candidate,未升级为最终版本)。
7. 候选方案 C:统一的 Counter 差分与状态机(已采纳)
- 假设:CSwitch / Wakeups / Disk Read / Disk Write 四个 counter 字段可以共用同一套差分逻辑与质量状态机,减少重复实现和不一致风险。
- 实现:
_counter_rate(event, row, key)以(target_pid, target_generation, source_epoch, reconnect_generation, adapter_id, key)作为身份键维护前值缓存;首次观测warmup;当前值小于前值判定为counter-reset(不产生负速率);窗口非正判定为invalid-window;否则输出candidate速率。 - 判定:采纳,是当前四个 counter 类指标共享的标准实现,也是
system_epoch/reconnect_generation参与身份键、保证重连后不跨窗口误算的关键设计。
8. 被证伪路线与停止条件
当前 devlog 中未发现 CPU/Sysmontap 领域有被系统性证伪并放弃的独立技术路线(不同于 Startup 领域的 xctrace 切换、Mapping 语义提升等)。这与 sysmontap 通道本身相对稳定、Instruments 官方长期使用同一服务有关。若后续出现相关实验记录,应在此补充,不在此处编造未发生的路线。
9. 最终方案为什么胜出
统一公式引擎 + fail-closed 归一化 + 统一 counter 状态机的组合胜出,原因:
- 把"gauge 直读、counter 差分、核数 fail-closed"这三类不同的语义收敛到少数几个可测试函数(
_system_metrics/_process_metrics/_counter_rate),而不是在每个指标里各自实现一遍,减少了不一致的可能; derive SESSION支持离线重算,意味着公式修订不需要重新采集真机数据即可验证,降低了后续演进的成本;- fail-closed 设计(核数未知就不归一化、counter 未见前值就 warmup)避免了"猜一个默认值"带来的虚假精度。
10. 从 POC 到产品化又踩了什么坑
- CORE-8(2026-09-05):新增 19 项 Python 公式 Registry ,其中分核 CPU、AvailableMemory 等均保持
candidate,明确"没有同场或真机证据的项未升级为数值 validated"——即使公式实现完成,也不因此自动认为证据充分。 - P2/P5 Foundation 自校准(2026-09-06):P2 批次 11 个指标(含 APP CPU、TotalCPU raw/normalized、Per-Core)在 USB iOS 17 受控启动真机 Session 上达到 11/11 internally-calibrated;同批验证了应用搜索/选中的过期结果 fail-closed 修复与
controlled-launch默认策略。真机侧同时核验了 73 个 User App(USB iOS 17)与 31 个 User App(Wi-Fi iOS 18)的设备快照读取。这一批证据证明的是 Perfowl 内部公式与质量语义的自洽,不是与外部工具的同窗数值对照——按用户决定,PerfDog 同窗对照(L4)在本批次保持not-tested。
11. 当前仍未关闭的门禁
- CPU 领域整体没有独立于其他指标域的专项真机验收批次;现有证据多依附于跨指标联合采集会话,E4 证据等级为"混合"而非专项。
ios.device.cpu.total.normalized的definitionVersion仍标注为candidate(v2),尚未见到升级为非 candidate 版本的记录。- 与第三方工具(如 PerfDog)的同窗数值对照仍是
not-tested,不得在任何场景下描述为"已交叉验证"。 - Per-Core 数组下标与物理核心类型(P/E)的对应关系没有独立证据,不应被当作可靠的核心身份标识。
12. 可复用工程经验
- 公式与展示分层:把"字段是 gauge 还是 counter"这类底层语义判断收敛到一个公式引擎里,比在多个展示位置各自处理更不容易产生不一致。
- fail-closed 优于假设默认值:核数未知就不归一化,比"假设 6 核"更诚实,也避免了跨机型出错。
- 身份键要包含重连/纪元信息:
_counter_rate的身份键包含source_epoch与reconnect_generation,这是避免"设备重连后误把新计数器当作旧计数器的延续"的关键设计,值得在其他领域的 counter 类指标中复用。 - 内部自校准与外部同窗校准是两回事:11/11 internally-calibrated 证明的是公式自洽,不能替代与第三方工具的同窗数值对照;知识库和产品文案都不应该混淆这两种证据。
13. 原始 devlog 索引
p2-collector-core-core8-metric-engine.md:RawMetricEngine 与公式先行表。p2-p5-foundation-self-calibration-plan.md/-result.md:P2/P5 自校准与真机应用选择闭环修复。
完整正文见 site/devlog/index.md 时间线或对应 /archive/ 归档页。
14. 延伸阅读
版本历史补记
| 日期 | 修订 | 来源 |
|---|---|---|
| 2026-10-26 | 补本月实验结论、失败路线与适用限制;早期阶段数字保留 | 月度梳理 |