外观
指标计算模型与窗口语义
Perfowl 的指标不是“收到一个字段就画一条线”。一个正式数值至少同时依赖:
text
Source Fact
+ Identity / Scope
+ Clock Domain
+ Window / Baseline
+ Freshness
+ Quality Gate
+ definitionVersion这页建立所有指标共享的计算理论。具体 metricID 的字段、单位和版本仍以 Registry 指标合同索引 与各 Canonical 指标页为准。
一、十类计算模型
| 计算模型 | 代表指标 | 核心算法 | 首点 / 窗口行为 |
|---|---|---|---|
| Gauge | APP CPU、Memory、GPU Utilization、Energy | 当前有效原值或明确单位换算 | 首个有效样本可发布;source 不可用时 missing |
| Cumulative Counter Rate | CSwitch、Wakeups、Disk | (current - previous) / elapsed | 首点只建 baseline;counter reset 后重新 warmup |
| Interval Rate | Device / Process Network | interval amount / interval duration | 必须有完整有效窗口;不同 clock domain 不混算 |
| Event Interval | FrameTime | 当前事件与明确前驱事件的设备时钟间隔 | 第一事件只建 anchor;断链后重新 warmup |
| Rolling Count | 新 Display FPS 目标模型 | trailing window 内事件数量 | 窗口随时间推进;source 健康但窗口无事件时可为真实 0 |
| Rolling Percentile | P95 FrameTime | 最近固定窗口 valid event 的 nearest-rank percentile | 样本不足时 warmup / missing,不用 0 填充 |
| Rolling Distribution | Refresh Rate 分布 | 对有效 source-native interval / rate 做时间窗口或 Session bucket | display/source 切换时必须断开 |
| Rolling Derived Metric | Frame Pacing Jitter | P95(FrameTime) - P50(FrameTime) | 依赖同一窗口中的两个有效统计量 |
| Session Aggregate | P50/P90/P99/Max、1% Low、Jank/Stutter | 对整段有效事件序列聚合 | 只消费符合 quality/scope 的样本 |
| Conditional / Source-native | Battery Power、Energy、GPU Counter | 物理条件公式或 Apple source-native value | 条件不成立时 missing/not-applicable;未知字段不猜单位 |
二、Source Cadence、Publisher Cadence、Report Cadence 是三件事
很多误解来自把“底层事件有多快”与“工作台多久刷新一次”混在一起。
text
Source Cadence
设备事件/采样原始到达节拍
↓
Domain / Metric Processing
逐事件或逐窗口计算
↓
Publisher Cadence
产品 MetricFrame / UI snapshot 发布节拍
↓
Report Cadence
在线统计、Session 聚合与最终报告节拍例如 FrameLifetime 可以几十次/秒到达,而产品工作台仍按约 1 秒发布一次 Display Performance snapshot。降低 UI 发布频率不能替代底层 source 降带宽;反过来,底层高频事件也不要求 UI 每条事件都重绘。
三、Freshness:什么时候可以沿用上一个值
不同指标的“新鲜度”规则不同。
| Freshness 类型 | 例子 | 没有新原始数据时的正确行为 |
|---|---|---|
| Gauge freshness | CPU、Memory | 可以在当前有效采样点发布最新 gauge;source 超时后必须 missing |
| Event freshness | FrameTime | 只有出现新的有效 event interval 才发布;不能重复上一帧 FrameTime |
| Window freshness | FPS、P95、Jitter | 依据当前滚动窗口重新计算;旧事件随窗口淘汰 |
| State freshness | foreground、Startup lifecycle | 状态变化本身会重置依赖前值的算法 |
| Conditional freshness | Battery Power | 物理前置条件一旦失效立即置空,不保持上一次放电值 |
因此:
text
CPU 没有在每个 UI tick 变化
≠ 必须立刻清空
FrameTime 没有新帧
→ 不得重复上一帧值
Display FPS source 健康 + 前台 + 最近 1 秒没有新 presentation
→ 可以是真实 0
source 不可用
→ FPS 必须是 missing,而不是 0四、Warmup 与 Baseline
依赖前值的算法都必须先建立 baseline:
text
Counter Rate
Network Delta
FrameTime
Rolling Window首个样本通常只能证明“source 已经开始返回事实”,不能凭一个点构造时间差。
例如:
text
counter sample #1
→ 保存 previous counter
→ quality = warmup
counter sample #2
→ current - previous
→ elapsed > 0
→ rateFrameTime 同理:source/reconnect/foreground/display 边界后的第一帧只重新建立 anchor。
五、统一断链合同
只要一个算法依赖“上一条”或“最近窗口”,下面任一边界发生时都必须评估是否清空状态:
sourceEpoch改变;reconnectGeneration改变;targetGeneration/ PID identity 改变;- target foreground → background → foreground;
- displayID 改变;
- cumulative counter 下降或 reset;
- clock domain / source timestamp 类型发生变化;
- schema 或 source role 发生变化。
默认原则:宁可重新 warmup,也不要跨不连续边界制造一个数学上可算、物理上不存在的值。
常见例子
text
PID 1564 counter
+ App 重启后的 PID 1832 counter
≠ 一个连续 ratetext
Display 1 FrameLifetime
+ Display 2 FrameLifetime
≠ 一个连续 FrameTime sequencetext
foreground 最后一帧
+ background SpringBoard 若干帧
+ foreground 第一帧
≠ 目标 App 一段连续帧时间六、0、missing、warmup、not-applicable 不可互换
| 状态 | 真实含义 | 能否参与统计 |
|---|---|---|
0 | 经过有效窗口和身份门禁后,系统事实确实为零 | 可以 |
missing | 没有足够事实得到这个值 | 不可以 |
warmup | source 已工作,但算法 baseline / window 尚未成立 | 不可以 |
not-applicable | 当前 App 架构或物理条件不存在该语义 | 不可以 |
not-foreground | foreground-device 指标当前不属于目标 App | 不可以 |
counter-reset / discontinuity | 前后样本不能安全连续计算 | 不可以 |
完整质量字典见 数据质量与 0 值判定准则。
七、三个典型算法示例
1. Network Rate
text
currentBytes - previousBytes
----------------------------
elapsedSeconds要求:同 source、同 identity、同 clock domain、elapsed > 0。counter 下降或进程 generation 变化后重新 warmup。
2. FrameTime
当前目标架构使用明确 presentation 前驱关系:
text
FrameTime = currentPresentation - previousPresentation真实实现必须使用设备 source timestamp / Mach timebase,不允许用 hostReceiveMonotonicNs 冒充帧发生时刻。Display Performance 切源完成前,当前 production source 以 Registry 合同为准。
3. Rolling FPS
目标 Display Performance 模型:
text
FPS(t) = count(valid presentation timestamps in (t-1s, t])它是一个窗口吞吐指标,不是 1000 / 当前 FrameTime。窗口可以借助 host monotonic 推进“现在”,但 host 时间只能用于窗口淘汰,不能生成不存在的 presentation timestamp 或 FrameTime。
八、时钟规则
任何差值计算都要先确认两个端点属于同一个 clock domain:
text
Device Mach ticks
↔ dynamic numer / denom conversion
Host monotonic
↔ host elapsed / receive / publisher window
Source-native Cocoa timestamp
↔ 仅与同源相邻 timestamp 相减禁止:
text
Device event timestamp - host receive timestamp
old source clock - new source clock
不同 display / generation 的 timestamp 直接相减具体时钟、bridge 与 Session timeline 见 数据流、时钟与断链规则。
九、公式版本为什么必须冻结
以下任何变化都应该视为指标定义变化,而不只是“实现优化”:
- source ownership 改变并导致语义改变;
- scope 改变;
- unit 改变;
- rolling window 长度改变;
- percentile 算法改变;
- freshness 规则改变;
- reset / discontinuity 规则改变;
- 取整、bucket 或合法 0 语义改变。
发生定义变化时,Canonical 页、Registry definitionVersion、报告和 replay 必须保持可审计一致。历史 Session 应按原始版本回放,不用新公式静默改写历史结果。
十、阅读顺序
text
本页:计算模型
↓
数据流、时钟与断链规则
↓
数据质量与 missing/0
↓
具体 Canonical 指标页
↓
Registry 指标合同索引2026-10-26 · 采样均值、来源Stat与会话派生量
原生结果窗的采样均值是选定区间内、同scope/unit/代际且符合numeric质量合同的有限值Σv/n;Collector Stat可能来自更密的来源序列或逐帧集合。即使同一Session,两者也须先核输入窗口、有效点基数、质量过滤和算法版本,不能直接当同一统计量。采样均值不是默认时间加权均值,可用点比例也不是连续时间覆盖率。
单核100%口径的进程CPU允许多核累加超过100%;除以同窗有效核心数才是相应整机容量份额,核心数未知不猜测,大小核时间份额不是性能等价。单位相同仍需核scope。跨工具还须同设备/系统/版本/场景和操作窗口,不用不同日期均值给精度结论。
会话AvgFPS为N×1e9/Σd_i;1Hz FPS算术均值与它并不相等。滚动P95均值不等于全程P95,事件率T不能只计有效间隔。10月26日用户试用暴露CPU/内存概览与Collector Stat统计基数需进一步逐源核对,目前未完成全面对比,不据此宣布算法错误或准确度校准。原生报告合同 · 帧派生Canonical。
版本历史增量:2026-10-26,补统计对象与跨工具比较方法,E1复盘,不改计算公式或实现。月度复盘与来源索引 · 实验判断方法