Skip to content

P95 FrameTime:帧间隔长尾 ​

平均 FrameTime 很容易把少量明显长帧稀释掉。P95 FrameTime 的目标是观察最近窗口里“较差的一批帧到底有多慢”,因此它比平均值更适合暴露偶发顿挫和长尾恶化。

2026-10-21 · 最新正式验收 ​

P95 ARM202/Lab29新独占五轮正式通过,600/600固定点有效、831实际消费者、36204完整Raw,全部231尾部样本保留;独立原生整数窗口/实际Core/导出核同。正式36/66、剩30,无独立参考标记6项,下一屏幕刷新率0/5。 适用设备A/目标App A/当次系统与受控配方,E4覆盖、来源和独立Raw派生算术通过;完整物理精度未校准,标记NO_REFERENCE_ACCEPTED_OWNER_POLICY、referenceAccuracyValidated=false、ownerReviewRequired=false。旧失败及全部尾部保留,不外推第三方App或所有设备。五轮结果。

2026-10-21 · 当前实现合同与验收边界 ​

以下为准备阶段快照(正式0/5、整体35/66),由上方最新验收记录承接。以下新策略仅用于携带p95PublicationPolicy=p95-window-segment.v2的新Raw,未标记历史回放保持旧路径。Registry 的activitytrace-framelifetime-p95.v1仍标识10秒nearest-rank公式,新增策略版本单独标识来源资格、segment和发表失效语义。当前软件E2,不将其称为真机已验收。方案与实际实施见专项记录。

来源、单位和可独立重算事实 ​

通道和服务为com.apple.instruments.server.services.activitytracetap,selector onlySignposts。ActivityTraceFrameLifetimeRawAdapter与FrameLifetimeDecoder是Perfowl自研适配与解码层,运行于pymobiledevice3的DTX /ActivityTraceTap内核;P95FrameWindow是Perfowl派生层,不是pymobiledevice3原生P95。只接纳pmd3.activity-trace.frame-lifetime.raw版本2、foreground-device、signpost-framelifetime和perfowl.display-frame-event/2,并核实白名单CoreAnimation/IOMFBServer/FrameLifetime、已解码/已验证目标、无掉包、包络与payload目标代际/epoch/reconnect一致。目标App仅用于归属,数值范围为前台整机呈现。

整数原生计算为:P=endMachTicks*numer//denom、previousP=previousPresentationMachTicks*numer//denom,gapNs=(endMachTicks-previousPresentationMachTicks)*numer//denom,frameTimeMs=round(gapNs/1_000_000,6)。gap先做整数差再换算;一般不能拿两个已取整P的差代替。有效正数、有限、非bool,前驱严格链接、refresh原生区间为正且gap不大于12个refresh周期。区间和归一化时间戳均用原生字段重算校验,不能信任被篡改的frameTimeMs。

实时窗口、时钟与质量 ​

最后有效呈现P及adapter观察到达host H,发表host N:T=P+(N-H),要求N>=H;这只是短期显示时间估计,H不是socket到达或设备事件时间。选同一连续segment内T-10_000_000_000 < P_i <= T的有效区间。n<5为null/warmup ;n≥5取整数rank=(95*n+99)//100,按值升序取第rank项,最后Python round六位小数(ties-to-even)。它不等于Session全量P95,也不等于最慢5%的均值。

身份/目标代际、epoch/reconnect、timebase或前后台转换立即开启新segment;无须等待snapshot。discontinuity /source-gap不沿用旧值集合;错误来源、掉包、原生值错误、倒退/重复Raw均清空值窗口。顺序高水位独立保留,错误不能通过清窗后重放旧数据重新凑够5点;同目标下epoch及同epoch reconnect不得倒退。外display事件不延长主display新鲜度。

host静默严格>1秒为null/stale-source,恰1秒允许;未来host为null/future-source。已有同设备时钟过期下界>2秒仍最终强制null/stale-device-source,下界小或缺桥不证明物理新鲜。缺值不补0;P95为正数区间统计,0不是有效FrameTime。4096点硬上界超界清空并锁定overflow,只在明确身份/epoch/reconnect/timebase/前后台新segment解锁,不能静默丢点后输出统计。

专属收据p95FrameWindow保存发表cut、P/H/T、左开右闭边界、segment、来源/身份、n/rank、首末原生戳和Raw序号、计算质量与最终publicationQuality。收据是审计材料,独立参考须从Raw原生整数字段和真实发表cut重建,不拿该收据或相同projector充参考。独立算术核同也不等于物理呈现精度校准。可控测试App的CADisplayLink回调/requestedHz仅证明刺激和调度,不能替代实际呈现真值。

已发现问题与避免方式 ​

规范化控制复现旧路径在断续、目标切换及无中间snapshot的前后台转换后仍保留旧P95。机制是旧共享窗口未在这些边界清空;新策略用独立状态即时处理。反控方法为先输入至少5个有效区间、注入边界且不发表中间snapshot,再确认输出null并重新暖机。适用于新策略的软件合同;尚不外推任何手机/App的现场发生率或精度。原始材料和失败开销结果保留在私有专项批次,公开知识只归纳可复用规则。

1. 定义 / 概念 ​

P95 是一个分位数:把当前窗口内的有效 FrameTime 从小到大排列,找到 95% 样本不超过的位置。它不是“最差 5% 的平均值”。

2. Scope 与 Unit / 单位 ​

字段合同
metricIDios.frame.time.p95
Scope foreground-device
Unit / 单位milliseconds
sourceactivitytrace-framelifetime
definitionVersion activitytrace-framelifetime-p95.v1

3. 系统服务 / 采集调用 ​

P95 不打开新的底层服务。系统服务仍是 activitytracetap 的 CoreAnimation IOMFBServer / FrameLifetime,采集调用由 ActivityTraceFrameLifetimeRawAdapter 提供逐帧事实;新策略由P95FrameWindow对 FrameTime 的合格连续区间做滚动统计,未标历史回放保留DisplayPerformanceProjector旧路径。

4. 公式 / 计算方式 ​

实时窗口固定为最近 10 秒:

text
window = valid FrameTime samples in trailing 10s
n = sample count

if n < 5:
    P95 = missing
    quality = warmup
else:
    rank = ceil(0.95 × n)
    P95 = sorted(window)[rank - 1]

Perfowl 当前使用 nearest-rank,避免不同语言或库默认 percentile 插值方式不一致。

5. 一个简单例子 ​

假设窗口中有 20 个有效 FrameTime,排序后第 19 个样本就是:

text
rank = ceil(0.95 × 20)
     = 19

因此 P95 取第 19 个值,而不是把最后几个值做平均。

6. 实时 P95 与最终报告 P95 不是同一个窗口 ​

text
实时 P95
→ 最近 10 秒
→ 用于发现“现在”长尾是否变差

Session P95
→ 整段有效 FrameTime
→ 用于测试结束后的总体分布

报告还会保留 P50 / P90 / P95 / P99 / Max。P50 更像典型体验,P95 观察明显长尾,P99 / Max 用于追极端尖刺。

7. Quality / missing ​

以下情况不允许继续沿用旧窗口:

  • sourceEpoch / reconnectGeneration 改变;
  • 目标 App 前后台切换;
  • display identity 改变;
  • FrameTime 发生 discontinuity;
  • valid 样本数重新低于算法最小门槛。

窗口重置后重新进入 warmup;缺失不能填 0。

8. 证据与适用范围 ​

P95 metric contract、Swift Registry、Python Source Contract 与 projector 单测目前为 E2。其底层 FrameLifetime source 在 iOS 17 有 E4 POC,但 P95 产品数值仍等待 R7 完整真机链验证,不能把 source E4 自动升级成 metric E4。

2026-10-03 增量:旧两轮实时样本已含有效滚动 P95,最终覆盖却误记 missing/0,CSV 亦漏列。本批修复把已发布样本中的有限且质量有效值计入最终覆盖,并在 CSV 末尾追加值/质量列;warmup 和缺值不补零。修复仅通过 E2 测试,新包 E4 与上游帧源间隙仍需复测。

9. 如何分析 P95 ​

典型组合:

text
P50 稳定 + P95 明显上升
→ 大多数帧仍正常,但少量长尾正在变坏

P50 和 P95 同时上升
→ 整体 presentation 节奏都在变慢

P95 上升 + Jitter 上升
→ 长尾同时破坏了节奏稳定性

再结合 Refresh Rate、Jank/Stutter 与 CPU/GPU/I/O 同窗,判断是否需要进入根因排查。

10. 版本历史 ​

版本日期修订要点
p95-window-segment.v22026-10-21P95专属来源/原生整数资格、连续segment、顺序水位、短期cut与静默/超界门;保留历史回放。E2软件准备,正式0/5。方案与实施。
current-display-device-lag-lower.v12026-10-04同钟过期下界>2s置空/stale-device-source,数值公式不改;22匹配/全量E2与b116安装E3通过,新真机E4未测、54项100%仍partial。G7。
v1(当前)2026-09-17从 Display 总览拆出独立 Canonical,冻结 10 秒 rolling window、nearest-rank 与 n<5 warmup 合同。
v1 输出链路补记2026-10-03公式不变;最终覆盖与 CSV 补记已有实时样本,E4 待新包验证。

继续阅读:FrameTime · Frame Pacing Jitter。

2026-10-04 · 当前窗的设备时钟过期保护 ​

同一已核Session/目标代际/重连且两源实测Mach timebase一致,lagLowerNs=max(0,sysmontap.EndMach−FrameLifetime.endMach)×numer//denom是过期下界,不是精确年龄。严格超过2s时,本实时Display指标置空、质量stale-device-source;age上界未知继续null。下界小/无钟不是当前新鲜证明,原host-silence、one-shot、warmup与缺值门保持。旧Raw和native历史数值不回填,完整当前窗/独立scope与五轮100%仍待新包验收。

版本历史增量:current-display-device-lag-lower.v1(原数值公式不改),E2同钟/代际/边界及原迟到数据离线对照通过,E4与全54可信目标仍partial。共享时钟定义 · G7实施与证据。

2026-10-21 · 自有 Metal 上屏参考的适用范围 ​

Lab27使用Apple MTLDrawable.addPresentedHandler / presentedTime记录自有CAMetalLayer的实际上屏时间,并独立记录GPU命令完成;两者不是同一事实。CADisplayLink和requestedHz只描述刺激请求,不能用于证明实际帧间隔。软件阶段已通过18项主机控制、实际ARM SDK和开发签名(E2),仍未取得本手机参考资格,不作为E4精度依据。

判断方法为:用设备Mach原生钟与CACurrentMediaTime首尾括号直接核桥,不拟合偏移;完整Raw与完整drawable呈现序列双向唯一配对,检查所有外来帧、缺失及窗口边缘,最后按相同10秒窗与相同n/rank比较P95。单层Metal可能缺少系统或其它surface帧,属于待证范围问题,不能以单向最近邻或相关性高认定整机参考。出现零/负数/非有限/缺失上屏时间时,保留原始数和IEEE位并记partial,不将其补成0ms、不删除样本。

该方法适用于自有App的物理参考资格调查;即使该候选无法覆盖foreground-device,P95的Raw原生整数算术仍可独立重算,不能豁免。具体刺激、误差门、成本门和待测项见专项方案与实施。版本历史增量:lab-p95-reference-candidate/1,2026-10-21,E2候选实现,正式仍0/5。

2026-10-21 · 真机首帧零上屏时间(E4自有App用例失败) ​

Lab27首个140秒用例保留7212次请求与7212回调,首个presentedTime为0,其余7211为正;回调已到达不保证获得有效上屏时间。实际原因仍待定位,不能直接归因硬件或采集算法。复现与判断应检查原生回调、请求生命、画布就绪/阶段、首尾完整性和全部丢失记录;不能删首点后把整轮改成通过。当前用例为partial、参考尚未资格,P95正式0/5。原始结果与下一步。

版本历史增量:lab-p95-reference-candidate/1真机准备记录,2026-10-21,E4自有App候选运行与首帧0失败,不是指标正式验收。

2026-10-21 · 画布挂窗与呈现就绪分开记录 ​

didMoveToWindow只说明window发生变化,不能证明视图已完成呈现;viewDidAppear表示呈现动画之后的生命周期事件,也不能替代实际drawable上屏账。Lab28候选准入同时要求前台、许可温度、挂窗、viewDidAppear、有限正数布局和可见状态,并在负载开始前准备Metal资源;记录各自Mach时间以核先后关系。撤窗或消失立即撤销准入;不提交额外预热帧、不删首帧。22主机控制及实际ARM SDK通过E2,真机效果尚待验证;Lab27首帧0原因仍未证实。该做法适用于自有UIKit/Metal测试场景的生命周期取证,不能外推第三方App或整机精度。方案与实施。

版本历史增量:lab-p95-canvas-readiness/1,2026-10-21,E2生命周期准入候选,正式P95仍0/5。

2026-10-21 · Lab28生命周期与成本实测(E4自有App范围) ​

加强准入后,完整normal和新生命recovery各7212正数严格递增上屏,预期35秒取消1501正上屏、所有pending/invalid0;过期、复用nonce和同时pending均未新增负载。旧Lab27首帧0原件与失败结论不改,本次不能证明旧失败根因。完整OFF/ON各140秒,CPU增0.071909个百分点/峰footprint增426032B,账本callback mean/P95为0.001175/0.001667ms。全部呈现/过渡/尾部保留,证据范围只覆盖自有Lab的行为及成本,不证明整机FrameLifetime同层同窗精度;下一须完整双向配对和产品Raw独立算术,正式P95仍0/5。方案与结果。

版本历史增量:lab-p95-canvas-readiness/1,2026-10-21,E4工具与成本资格,非指标正式验收。

2026-10-21 · 原生时间单位相同不代表时钟域相同 ​

在完整Lab28产品诊断中,Raw native Mach与自有App absolute/media域相差约4618秒,直接≤0.25ms匹配为0。相同timebase不能证明时钟域相同:continuous可包含休眠时间,而absolute不包含。现有原件未采continuous,不能通过两序列拟合offset把本轮补成参考,也不能将0匹配解释为硬件坏或一定没有参考。下一候选只增加首尾两次continuous→absolute→media→absolute→continuous原生括号,以不确定区间及首尾交集核桥;真实域归属仍待实测。此方法适用于不同Mach时间源的同窗对照,不能仅凭数值接近指定域。方案与原始结论。

本次7242完整Raw与191实际产品样本的独立原生整数P95、消费cut、窗口n/rank及Core/CSV/JSONL核同;诊断首120机会只有119有效,maxgap2.000264334秒超过2秒,仍未就绪。独立算术核同与连续覆盖通过分别判断,不以缺独立物理参考豁免已观察异常。版本历史增量:p95-native-clock-investigation/1,2026-10-21,E4诊断事实、E2 Lab29桥控制通过,未取得物理参考资格或正式验收。

2026-10-21 · 原生钟桥与消费者发表边界实测 ​

Lab29在首尾两次原生括号中同时记录continuous与absolute,交集宽416.666667ns;7212个有效drawable均与Raw双向唯一匹配。全7250 Raw另有38帧不能归入自有Metal,21帧在最初1.638107秒内,来源尚未证明。判断完整参考必须保留这些点;只比已匹配点会漏掉启动窗口的整机范围差异。本次固定首120仅108个物理窗口合格,不能把局部精度结果当成全窗精度。

窗口核对还必须使用实际realtimeConsumeMonotonicNs <= sample.monotonicNs的消费cut。App完整物理历史可能含发表时产品尚未消费的帧,直接套10秒时间边界会出现n/rank不一致;配对完成后先按实际消费cut确定可比集合,再用独立App呈现间隔求分位数,不以产品receipt中的P95当期望。本例128个合格窗口最大差约0.000000713ms,其余全部保留。上述依赖原生钟桥、完整配对及可审计消费时间,不能外推缺少这些字段的历史数据。

产品新诊断155实际样本与7250完整Raw的独立整数算术、实际Core与CSV/JSONL核同;固定首120全valid、maxgap1.018823333秒,通过覆盖。它仍是E4诊断,不是正式五轮通过;旧Lab28覆盖失败保持原结论。Apple Instruments官方有Frame Lifetimes轨道,本机已识别目标与模板,但本次Animation Hitches实际断连,exit0及保存trace不能证明完整参考有效。详见方案与实际结果。

版本历史增量:p95-native-clock-consume-cut/1,2026-10-21,E4完整诊断与部分物理参考、正式0/5;无参考正式政策不得豁免异常或独立Raw算术。

2026-10-21 · 当前参考资格调查结论 ​

不同模板Metal System Trace也在0.326165秒报告设备断连;Animation Hitches仅0.349568秒,已导出的Frame Lifetime和surface swap表均0行。因此本机当前Apple通道没有完整可用的同场参考,不能用exit0或trace存在替代数据完整性。自有Metal的局部参考仍保留,整机初期额外帧不删除;不能断言Apple工具永久不可用或确定硬件故障。按Owner授权,后续完整无异常五轮及独立Raw算术通过后可带NO_REFERENCE_ACCEPTED_OWNER_POLICY正式计数,referenceAccuracyValidated=false、ownerReviewRequired=false;当前仍0/5,不将准备诊断计为正式通过。调查与候选表。

2026-10-21 · 执行超时的证据边界 ​

冷启动请求和UI启动等待均有期限,ready文件仅证明生成时就绪;上下文接续后需同时确认driver仍活跃、ready未到期再Start。若已超时,迟到Session完整保存但不能补成正式轮;实际plan/manifest用于判定采集配置与封口,不依赖UI旧计数。本次E4实测启动衔接超时,12个旧负载保全且无第五目录;不据此认定硬件或数值算法故障。P95仍未通过,下一完整新attempt。来源。

版本历史增量:2026-10-21,新增有界ready与迟到Session判定方法,未改p95-window-segment.v2公式或正式数量。

版本历史增量:p95-window-segment.v2,2026-10-21,ARM202/Lab29新独占五轮E4正式通过,完整原生整数/consume cut/n/rank及实际消费者逐样本核同;无完整独立物理参考,按Owner标记政策计数,非准确度校准。本批结果。

Perfowl · Performance Observer