外观
StartupTiming 启动阶段指标 v14
定义
StartupTiming 的 metricID、业务公式和展示语义继承 v13。v14 将屏障收紧为 挂起源就绪:目标 PID 先挂起存在,CoreProfile 首个非空、timebase 合法且 trace header 含该 PID 的 chunk 先写入 immutable Session,然后才 SIGCONT。因目标已在 header 中可精确归属,Startup 订阅收窄为当前阶段 decoder 真正消费的 4 组事件。
metricID、scope、unit 与来源字段
| metricID | 定义 | scope | unit | 来源字段 |
|---|---|---|---|---|
ios.process.startup.app_launch_total_ms | App Launch 完整首尾耗时 | process | milliseconds | System Interface begin → Initial Frame terminal |
ios.process.startup.system_interface_ms | System Interface Initialization | process | milliseconds | 版本化 lifecycle mapping 完整 Span |
ios.process.startup.static_runtime_ms | Static Runtime Initialization | process | milliseconds | 版本化 lifecycle mapping 完整 Span |
ios.process.startup.uikit_initialization_ms | UIKit Initialization | process | milliseconds | 版本化 lifecycle mapping 完整 Span |
ios.process.startup.uikit_scene_creation_ms | UIKit Scene Creation | process | milliseconds | 同 generation 的完整同名 Span之和 |
ios.process.startup.will_finish_launching_ms | willFinishLaunchingWithOptions() | process | milliseconds | 版本化 lifecycle mapping 完整 Span |
ios.process.startup.did_finish_launching_ms | didFinishLaunchingWithOptions() | process | milliseconds | 版本化 lifecycle mapping 完整 Span |
ios.process.startup.scene_will_connect_ms | sceneWillConnectTo() | process | milliseconds | 版本化 lifecycle mapping 完整 Span |
ios.process.startup.scene_will_enter_foreground_ms | sceneWillEnterForeground() | process | milliseconds | 版本化 lifecycle mapping 完整 Span |
ios.process.startup.initial_frame_rendering_ms | Initial Frame Rendering | process | milliseconds | UIKit begin → 呈现 terminal |
ios.process.startup.observed_running_ms | launch 请求到观察到进程 | process | milliseconds | launch.requested.raw → observed-running/rebound |
ios.process.startup.foreground_ready_ms | launch 请求到观察到前台 | process | milliseconds | launch.requested.raw → observed-foreground |
Registry 事实源为 MacApp/Sources/PerfowlCore/PerformanceModels.swift;v14 未新增 metricID。
业务计算、窗口、聚合与取整
text
coreTimestampNs = floor(coreMachTicks × coreNumer / coreDenom)
spanDurationMs = (endCoreTimestampNs - startCoreTimestampNs) / 1,000,000
phaseTotalMs = sum(同 phase 的所有完整 Span durationMs)
appLaunchTotalMs = (initialFrameEndTimestampNs - systemInterfaceBeginTimestampNs) / 1,000,000- 窗口是一次
controlled-cold-launch的单一 PID/generation,不跨启动聚合。 - 同名阶段按线程 stack 配对;阶段为完整 Span 求和,总时间用首尾锚点差。
- KDebug 跨 CPU/分块按 Mach tick、到达序排序;Double 全精度保存,UI 才格式化。
- 缺失、未闭合、跨 generation、负耗时和不可解码值均为
null/—。
Fixture Mach 桥原始字段
| 字段 | 含义 | 约束 |
|---|---|---|
sequence | 本次进程内 marker 序号 | 从 1 单调递增 |
phase / edge | 生命周期阶段及 begin/end | 每阶段唯一闭合 |
machAbsoluteTicks | 回调边界调用 mach_absolute_time() 的原始 tick | UInt64 正整数 |
machNumer / machDenom | mach_timebase_info | 正整数,且本 Session 不变 |
injectedDelayMs | Fixture 单变量延迟 | 0–2000 ms |
bufferMode | CoreProfile 实际源配置 | 仅 0 或 1;同批不混合 |
samplingTriggerEnabled | 是否发送第二 sampling trigger auxiliary | Startup 因果批次必须为 true |
samplingIntervalNs | sampling trigger 的 si | 固定 5,000,000 ns |
samplingTriggerVersion | 冻结配置来源版本 | py-ios-device-app-lifecycle.2.4.25 |
streamPhase | chunk 到达阶段 | active 或 post-stop-drain |
endOfStream | 是否为 stop 后空结束通知 | boolean |
coreProfileDrainStatus | Session 结束排空状态 | not-required / end-of-stream / quiescent / timeout / failed |
coreProfilePostStopChunkCount | stop 后仍写入 raw Session 的 chunk 数 | 非负整数,不缺值填 0 |
coreProfileDrainIdleSeconds | 静默完成窗口 | 固定 2 秒 |
coreProfileDrainMaxSeconds | drain 总等待上限 | 固定 6 秒 |
本地文件只保存 Fixture 自身的受控数据;进入公开证据前移除设备与签名身份。
同钟换算与完整性公式
text
fixtureTimestampNs = floor(fixtureMachTicks × fixtureNumer / fixtureDenom)
coreTimestampNs = floor(coreMachTicks × coreNumer / coreDenom)
markerDurationMs = (fixtureEndNs - fixtureBeginNs) / 1,000,000
markerDelayErrorMs = abs(markerDurationMs - injectedDelayMs)
markerToleranceMs = max(5 ms, injectedDelayMs × 5%)
sameTimebase = fixtureNumer == coreNumer AND fixtureDenom == coreDenom
insideCoreWindow = coreMinMachTicks <= fixtureBeginTicks <= fixtureEndTicks <= coreMaxMachTicks
clockBridgePassed = sameTimebase AND insideCoreWindow
AND markerDelayErrorMs <= markerToleranceMs
AND identityVerified AND droppedEventHighWater == 0受控启动的数据源 readiness 先于上述桥接公式执行:
text
prelaunchSourceReady = firstCoreProfileChunkObserved
AND firstChunk.byteLength > 0
AND firstChunk.timeConfig.numer > 0
AND firstChunk.timeConfig.denom > 0
semanticCalibrationLaunchAllowed = prelaunchSourceReady
if debugID == 0x25010004 AND arg0 > 0 AND arg1 > 0:
threadPid[arg1] = arg0v13 的受控启动屏障优先于上述 v9 首 chunk readiness:
text
sourceActivationReady = coreProfileSetConfigSent
AND coreProfileStartSent
AND coreProfileStartAckObserved
resumeAllowed = targetSuspended AND sourceActivationReady
launchRequestMonotonicNs = sigcontDispatchMonotonicNslaunchBarrierMode=process-control-suspended-v1,launchRequestBoundary=process-resume,resumeSignal=SIGCONT。- 首 CoreProfile chunk 允许在 resume 之后到达;目标 PID 在 CoreProfile 启动前已存在且保持挂起,trace header 可用于精确归属。
- 挂起、start ack、单消费者启动、resume 和 PID 归属任一失败时 fail closed。
v14 进一步要求真实数据就绪后才 resume:
text
startupSuspendedFilters = {
0x1F070000, 0x2BDC0000, 0x2B870000, 0x31CA0000
}
preResumeSourceReady = firstChunk.byteLength > 0
AND firstChunk.timeConfig.numer > 0
AND firstChunk.timeConfig.denom > 0
AND traceHeader.threadPidMap contains suspendedPID
resumeAllowed = targetSuspended AND preResumeSourceReadylaunchBarrierMode=process-control-suspended-source-ready-v1;首 chunk 先写盘,resume 后再写launch.requested.raw。v14 不使用动态线程发现过滤类;header 缺少目标 PID 时 fail closed,不用事件邻近猜测。
首 chunk 必须先写入 immutable raw Session,再发出
launch.requested.raw。后续采集复用同一 iterator/subscription,不创建第二 DTX reader 或 owner。
prelaunch trace header 尚无目标进程时,精确承接 CoreProfile
PERF_THD_Data的arg0=pid/arg1=tid作为动态 thread 归属;该字段语义来自冻结 pykdebugparserkperf_thread_info_sample解码。CoreProfile
bufferMode写入 raw payload;重复性和因果聚合只接受同一模式,不对不同设备端缓冲策略做数值拼接。readiness 超时、空 chunk 或 timebase 缺失时,本次启动语义校准 fail closed,不用无覆盖窗口的数据继续计算。
Startup trace 的 CoreProfile
setConfig:必须使用同一 DTX service/channel 发送两个有序 auxiliary:mainTraceConfig在前,samplingTriggerConfig在后;不得为第二配置建立新 socket。sampling trigger 固定为
tsf=[65537]、ta=[[0],[2],[1,1,0]]、si=5,000,000ns、tk=1;UUID 每 Session 随机且不进入公开证据。非 Startup 的 FrameTime/FPS CoreProfile 路径不启用第二 trigger。启用与未启用的 Session 只做修正前后对照,不混合聚合。
text
samplingTriggerCompatible =
allSessions.samplingTriggerEnabled == true
AND allSessions.samplingIntervalNs == 5_000_000
AND allSessions.samplingTriggerVersion == "py-ios-device-app-lifecycle.2.4.25"
coreProfileDrainPassed = coreProfileDrainStatus IN {"end-of-stream", "quiescent"}
AND coreProfileDrainIdleSeconds == 2
AND coreProfileDrainMaxSeconds == 6
startupRequiredFilters = {
0x07000000, 0x25010000, 0x1F070000,
0x2BDC0000, 0x2B870000, 0x31CA0000
}
filterSetExact = actualKdebugFilters == startupRequiredFilters
windowHeadroomMs = (coreMaxMachTicks - markerEndTicks)
* coreNumer / coreDenom / 1,000,000samplingTriggerCompatible仅用于显式启用 trigger 的研究批次;正式路径默认关闭时不要求该式。quiescent表示 stop 已发出、唯一消费者保持工作、最后一条 post-stop 消息后连续 2 秒无新消息,且总等待未超过 6 秒;这是对未承诺空结束通知的 CoreProfile 协议的可审计完成条件。启动阶段进入因果与 mapping 门禁前必须满足
coreProfileDrainPassed。总等待超时情况下即使 marker 落入窗口,也只保留诊断候选。6 组最小充分过滤类分别覆盖线程→PID、
PERF_THD_Data、System/Static、UIKit/AppDelegate/Scene 及 Initial Frame terminal;集合外事件不参与当前版本计算。filterSetExact=false的 Session 不与 v12 聚合;windowHeadroomMs < 0表示阶段边界被窗口截断,指标保持null/—。这里不拟合 offset:两源都显式使用同一设备的
mach_absolute_timetick,offset 固定为 0;若任一源无法证明为 Mach absolute,状态为unsupported-clock-schema。timebase 变化、marker 倒退、重复边界、旧文件混入、跨 PID/generation 或窗口外均拒绝桥接。
control的注入延迟为 0;仅校验耗时非负且边界闭合,不把真实回调执行时间强制为 0。
因果与 Mapping 门禁
text
controlMedianMs = median(至少 3 个 control 完整 CoreProfile Span)
delayedMedianMs = median(至少 3 个 delayed 完整 CoreProfile Span)
observedDeltaMs = delayedMedianMs - controlMedianMs
delayErrorMs = abs(observedDeltaMs - injectedDelayMs)
toleranceMs = max(20 ms, injectedDelayMs × 20%)
fixtureEvidencePassed = clockBridgePassed AND delayErrorMs <= toleranceMs最终 mapping 同时要求:Fixture Mach 桥通过、单变量因果门禁通过、Mapping v3 同系统至少 3 次且至少 2 App 的重复性通过。多个候选同步响应时为 ambiguous。
质量语义
auditable:同一 Mach absolute 时间基、完整边界、窗口与数据质量门禁全部通过。unsupported-clock-schema:任一源不是可证明的 Mach absolute tick 或 timebase 不合法。timebase-mismatch:Fixture 与 CoreProfilenumer/denom不一致。outside-core-window:Fixture marker 不在本次 CoreProfile 记录窗口。source-not-ready-before-launch:受控 launch 前未获得非空且 timebase 合法的 CoreProfile 首 chunk。target-thread-unresolved:trace header 与动态PERF_THD_Data均未建立目标 PID 的 thread 归属,目标 Span 保持缺失。marker-incomplete:begin/end、序号或配对不完整。marker-delay-out-of-tolerance:Fixture 注入执行自身未达到门槛。missing:marker 文件、CoreProfile 记录、身份或质量事实缺失。
这些状态与业务指标的 candidate/partial/missing 分开记录;缺值不写 0。
当前校准状态
- E4:iOS 17 隔离探针确认 ActivityTrace 与 CoreProfile 并发会令 CoreProfile 0 条;单 provider、双 provider 结果相同,CoreProfile 单源对照为 401,517 条。因此 ActivityTrace 不进入实时启动链。
- E2:Fixture Mach marker、沙箱取回、桥接审计器与单元测试已实现。
- E4 iOS 17 根因证据:签名 Fixture 已安装;control 短 Session 取回 4 条 marker,timebase 一致、identity verified、drop=0,但 marker 早于首个 CoreProfile 解码窗口,状态为
outside-core-window。 - E4 iOS 17:prelaunch readiness 修正后,control 的 marker、timebase、identity 与 drop 门禁通过;300ms delayed 仍高概率为
outside-core-window。 - E4 iOS 18:开发描述文件更新、Fixture 安装及 control 时钟桥已通过;未启用第二 trigger 的 300ms willFinish 基线仍为
outside-core-window。 - E4 sampling trigger 对照:iOS 17 与 iOS 18 的 willFinish 300ms 仍为
outside-core-window,不能证明第二 trigger 有独特窗口收益;正式路径默认关闭。 - E4 stop/drain 结果:iOS 17/18 四轮 willFinish / didFinish 300 ms 均达到 identity verified、drop=0、marker 完整与 drain=
quiescent,但均为outside-core-window;drain 不是剩余根因。 - E4 窗口诊断:iOS 17 失败轮的 CoreProfile 窗口约 493–505 ms,iOS 18 约 214–224 ms;16 MiB raw chunk 证明设备端缓冲占用是下一个校准变量。
- E4 待验收:使用 6 组最小充分过滤集重跑两种系统的 willFinish / didFinish;两端因果门禁未通过前,内部阶段继续
null/—。
版本历史
- v14(2026-09-06):首个真实 CoreProfile chunk 与 trace header PID 归属先于恢复,Startup 过滤集收窄为 4 组必需阶段事件。来源:Startup 挂起源就绪屏障 v1 方案。
- v13(2026-09-06):新增 ProcessControl 挂起启动屏障,将源启动 ack 与 App 恢复边界固化为可审计时序。来源:Startup 挂起启动屏障 v1 方案。
- v12(2026-09-06):新增 6 组 CoreProfile 最小充分过滤集、过滤同质性与窗口余量门禁。来源:Startup 最小充分过滤集 v1 方案。
- v11(2026-09-06):新增 CoreProfile stop-before-cancel、2 秒静默/6 秒总上限尾部 drain、结束状态与 post-stop raw 标记;sampling trigger 因 E4 无窗口收益改为默认关闭候选。来源:Startup CoreProfile Stop/Drain v1 方案。
- v10(2026-09-06):增加同一 pymobiledevice3 DTX owner 下双 auxiliary CoreProfile sampling trigger、源配置同质性与不混合聚合门禁。来源:Startup CoreProfile Sampling Trigger v1 方案。
- v9(2026-09-06):基于 iOS 17
outside-core-windowE4,新增首 CoreProfile chunk 写盘先于 controlled launch 的 readiness 门禁。来源:Startup Prelaunch Readiness v1 修正方案。 - v8(2026-09-06):基于真机互斥证据,将并发 ActivityTrace 方案修订为 Fixture Mach absolute 离线桥。来源:Startup Mach Clock Bridge v1 修订方案。
- v7(2026-09-06):提出 ActivityTrace → CoreProfile 锚点桥,后被 E4 并发互斥证据取代。
- v6(2026-09-06):冻结 Fixture 单变量延迟与 Semantic Evidence 质量契约。