外观
Startup Observation(Process Observed Running / Foreground Ready)
2026-10-28 · 普通报告展示调整
这两项是主机从发出启动请求到外部观测到目标进程运行/进入前台的延迟,包含查询、传输与主机调度时间,不是设备端启动阶段或App Launch Total。为消除“进程启动耗时/进入前台耗时”名称歧义,普通UI、摘要CSV及当前两页Excel不再混列;原始会话、Registry 与开发者诊断路径保留,计算公式不变。启动总耗时及阶段继续从设备端单次启动结果读取。该展示调整仅有E2软件证据,不是启动精度重新验收。本次决策与验证。
作用域属性:[进程级 · 目标 App 专属](Process Scope ) 当前状态:candidate
1. 定义与业务价值
这两个指标回答的是一个更粗粒度但更轻量的问题:从 Perfowl 发出启动请求,到主机外部观测到目标进程"在跑"、"已经到前台",大约用了多久。 它们不依赖 CoreProfile 深度解码,因此可以在 CoreProfile 深度链路不可用、或作为该链路的独立外部对照时提供启动信息。它们不是 First Frame,也不能替代 App Launch Total。
2. metricID / scope / unit / source
| 指标 | metricID | scope | unit | source | sourceKey | definitionVersion |
|---|---|---|---|---|---|---|
| Process Observed Running | ios.process.startup.observed_running_ms | process | milliseconds | lifecycle-observer | observedRunning-launchRequested | startup-observation.candidate.v2 |
| Foreground Ready | ios.process.startup.foreground_ready_ms | process | milliseconds | lifecycle-observer | observedForeground-launchRequested | startup-observation.candidate.v2 |
以上字段来自当前 MacApp/Sources/PerfowlCore/PerformanceModels.swift Registry,与 site/data/metric-contracts.json 快照一致。
3. iOS 系统原理
iOS 没有对外暴露一个"进程已完全启动"的公开事件流;Perfowl 通过主机侧对目标进程状态的轮询式外部观测(而非设备内核 signpost)间接推断"进程已在运行""已进入前台"这两个状态迁移,本质上是黑盒外部观测,精度受实际轮询间隔、服务调用耗时和调度影响,配置周期并不是实际误差保证。
4. 系统服务 / 通信通道 / 采集命令与实现
- 触发事件:
launch.requested.raw,由MacApp/Sidecar/perfowl_collector_core/startup_timing.py::launch_request_envelope生成,service 为com.apple.instruments.server.services.processcontrol(processcontrolchannel,launchselector),adapter 自报perfowl.startup-control.raw,底层复用 pymobiledevice3 ProcessControl(PMD3_CANDIDATE版本锁定)。 - 观测服务:
com.apple.instruments.server.services.deviceinfo,DTX ;自研adapters.py::LifecycleRawAdapter/_LifecyclePollStream调用 pymobiledevice3DeviceInfo.proclist(),精确匹配目标应用标识,再记录生命周期迁移。当前路径在进程列表缺少应用标识时不会凭名称猜测;缺失支持需单独验证,不外推所有平台。 - 观测事件:
lifecycle.observed.raw,携带observed-running/observed-rebound/observed-foreground等状态标签;由startup_timing.py::analyze_startup在这些事件中按保留事件顺序选择严格晚于请求、代际匹配的首个running/foreground记录;实时路径保留相同首到语义,不用后续重复替换。 - 这是 Perfowl 自研的轻量适配层,不是 pymobiledevice3 原生返回的成品指标——pymobiledevice3 只提供进程控制与状态查询能力,"从请求到观测到运行/前台"的差值计算和名义轮询间隔汇总完全是 Perfowl 自己实现(
StartupTimingReportdataclass,STARTUP_ALGORITHM = "startup-observation.candidate.v2")。
5. 原始字段与字段语义
launchRequestedMonotonicNs:发出受控启动请求时的 host 侧time.monotonic_ns()时间戳;observedRunningMonotonicNs:host 侧首次观测到目标进程处于observed-running/observed-rebound状态的时间戳;observedForegroundMonotonicNs:host 侧首次观测到observed-foreground状态(或带foreground=True标记的 running/rebound 事件)的时间戳;pollIntervalSeconds:轮询周期原始字段,用于生成兼容字段pollingErrorUpperBoundMs;它只是名义间隔汇总,不含实际调用/调度耗时。
6. 精确公式
text
ObservedRunningMs = (observedRunningHostNs - launchRequestedHostNs) / 1,000,000
ForegroundReadyMs = (observedForegroundHostNs - launchRequestedHostNs) / 1,000,000
pollingErrorUpperBoundMs = max(pollIntervalSeconds 遍历所有相关事件) × 1,000来源:startup_timing.py::_elapsed_ms 与 _polling_error。两个耗时字段都使用 host 侧 receive monotonic clock(host_receive_monotonic_ns),不是设备 mach timestamp;因此不应与 app-launch-total.md 的 CoreProfile mach 时间戳做毫秒级逐点对齐比较——它们是两个不同的 clock domain。
7. Clock / Window / Freshness
- Clock domain:host receive monotonic(Python
time.monotonic_ns()),与 App Launch Total 使用的设备 mach absolute time 是不同 clock domain。 - Window:单次受控启动产生一对(或缺失一侧)观测值,不做滑动窗口聚合。
- Freshness:值在观测到对应状态迁移事件时确定;兼容字段
pollingErrorUpperBoundMs只汇总配置间隔,并非可保证的物理误差上界。数值对照须保留每次服务调用的主机读取前后界、最后未见/首次见区间;仅复算同一Raw字段不是独立准确性证据。
8. Baseline / Reset / Discontinuity
无前值依赖;每轮受控启动独立计算一次,无 counter reset 语义。
9. Quality:valid / candidate / missing
launch.requested.raw缺失(未发起或事件丢失)→ 整体 quality 为missing,reasonlaunch-request-missing;- 存在
running或foreground观测记录 → qualitycandidate; - 两者都未观测到 → quality
missing,reasonstartup-terminal-observation-missing。
10. 合法 0 的条件
理论上不存在合法的 0 值:从发出启动请求到外部观测到状态迁移必然消耗可观测的正时间。计算结果为 0 或负值(end.host_receive_monotonic_ns <= start.host_receive_monotonic_ns)会被判定为无效,返回 None(即 missing ),不会展示为 0。
11. 当前证据、校准与平台覆盖
2026-10-17 当前验收更新(E4):内部179/自有目标App A五个新生命、5个Session按L4-S8固定状态与迟滞门通过;仅Process Observed Running,前台观察仍待独立验收。Raw公式、所有live/CSV值与实际安装二进制副本报告一致、质量candidate。参考同系统服务,新鲜度unknown;不是物理精度或全平台保证。历史下列“尚未专项”是此前状态,现由本增量承接,不回改旧实验数字。本批证据。
- 该路径为纯主机侧观测,不依赖 CoreProfile 深度链路,理论上在 CoreProfile 端点缺失、九阶段
partial的场景下仍可提供进程运行/前台的外部证据;当前 knowledge 库尚未整理出这两个指标独立于 Total/九阶段的专项 E4 证据批次(现有 E4 记录多以 Total 与九阶段为核心指标登记),后续需要在 Phase 10 全站审计或独立 devlog 批次中补充这两个指标自身的 E4 证据链接。 - 2026-10-17专项软件(E2):正时差规则的实时/离线11项对照通过,旧0值边界有3项失败复现;启动相关390项、实时60项、录制13项通过。自有启动工具70项控制通过并完成实际iOS SDK链接;它尚未完成新版本手机资格或正式五轮,不登记本指标E4通过。历史其他启动路径证据不移植到本首项。当前方案与实施。
12. 如何分析:能得到什么结论,不能得到什么结论
能得到:进程大约何时被主机观测到"在跑"、大约何时进入前台,可作为 CoreProfile 深度链路的粗粒度降级信息或交叉对照。
不能得到:不能当作 First Frame 或业务可用性的替代;不能与 App Launch Total 做毫秒级逐点等价比较(clock domain 不同、精度合同不同);不能用于九阶段级别的代码归因。
13. 常见误区
- 把
Process Observed Running当作"进程已完全初始化":它只表示主机侧观测到某个运行状态标记,可能早于或晚于真实的完整初始化完成; - 把这两个指标的耗时与 App Launch Total 直接相减做"验证":两者 clock domain 与精度合同不同,做逐点比较没有意义。
14. Legacy / 历史实现
startup-observation.candidate.v2 是当前唯一实现版本;未发现更早的历史候选版本记录。
15. 版本历史与来源批次
本页由 site/knowledge/metrics/startup-timing.md v47(2026-09-17)拆分而来。
| 版本 | 日期 | 修订要点 |
|---|---|---|
| v11(本页文档) | 2026-10-17 | 前台运行观察五新轮限定E4通过,原字段/身份/完整读界与实际报告一致;candidate/非物理精度,新设计3/66。证据。 |
| v10(本页文档) | 2026-10-17 | 原生采集与Apple测试指令通道分层诊断、资格失败Start0/unknown边界;前台未验收。记录。 |
| v9(本页文档) | 2026-10-17 | 前台独立参考严格bool三态与完整读界的软件控制,未增加指标验收数。前台合同。 |
| v8(本页文档) | 2026-10-17 | 179进程运行观测限定E4五新轮验收,Raw/live/CSV/实际派生报告一致,预定状态/迟滞工程门;不等于物理校准,不顺带接受前台/Total/九阶段。L4-S8。 |
| v7(本页文档) | 2026-10-17 | 参考读前收尾预留与未覆盖尾段;66项软件控制,真实再资格待续;L4为报告/导出型,不恢复既已移除的Running曲线。来源:L4-S7。 |
| v6(本页文档) | 2026-10-17 | 179包内来源与真实采集准入分层;未武装源不能判为采集失败,对照窗口尾读超时保留partial。仅E2/E3、首项0/5。来源:L4-S6。 |
| v5(本页文档) | 2026-10-17 | 内部178覆盖与来源核同、Mac/Lab签名阻碍分离及首次无窗口恢复边界;仅E2/E3准备,首项真机0/5不变。来源:L4-S4。 |
| v4(本页文档) | 2026-10-17 | 补冻结包来源与源码/包内测试分层;10组合成报告及87项包内运行控制只属E2,未安装、不新增E4。来源:L4-S3。 |
| v3(本页文档) | 2026-10-17 | 补充条件读界、同源参考/缓存边界、失败封存与工具E2状态;不变更公式、不宣告新E4。来源:L4-S2。 |
| v2(本页文档) | 2026-10-17 | 澄清名义轮询字段不是真实误差保证、正时差边界/首到语义及L4 E2状态;算法标识仍candidate.v2,不改Total。来源:L4首项。 |
| v1(本页) | 2026-09-18 | 从 startup-timing.md 拆出,成为 Observation 指标独立 Canonical 。 |
验收中的可复用判断 · 2026-10-17
- 零值遮蔽:只在最后计算时拒绝0仍不足够——若先选中相等时间戳的第一条,它会挡住后续真实正时差事件。离线先筛
end > start、实时先拒end <= start,并对照“无后续/有后续/前台先到/错代际/重复”负控。本次为合成E2发现,不声称手机发生过零耗时。 - 请求/应答分界:异步启动调用前后可能相隔明显时间。请求锚点必须在await之前采样,并将该值明确写入Raw;调用完成才取时刻会漏算等待。正常UI路径本来已在调用前,修复的是旧有界录制入口;两者不能混称同一故障。
- 身份与时钟分层:目标进程变化由来源推进代际,正常实时协调器另经身份验证后绑定投影;合成helper能接受某种输入,不等于生产入口可达。主机外部观察与App内部回调/设备Mach端点分别记录,禁止直接跨域相减或把onAppear标成物理首帧。
独立读界的使用限制 · 2026-10-17(E2)
- 问题与判断:两次轮询看起来间隔固定,不代表知道状态在两次读之间的精确变化点。ProcessControl精确查询→DeviceInfo列表→同应用精确查询全部保留调用前后界;双查与唯一身份一致才记看见,失败/矛盾记unknown,不凭名称猜身份。来源字段不足时资格不成立。
- 保守公式:最后未见读为
[a,b]、首次看见读为[c,d]时,条件变化界取[a,d],不是[b,c]。前提是系统服务反映当前状态;缓存新鲜度未知就不能解释成真实出生时间。无启动前未见或跨生命时不估算。 - 避免误验收:独立读取器使用同系统服务,属于交叉核对而非独立物理精度仪器;App生命周期回调不是物理首帧。读取窗口结束前的未观测尾部单列,不能以配置时长声称连续覆盖。包装层close返回也不证明被库抑制异常的底层句柄完整关闭,实际资源资格另验。
- 复现与范围:57项mock/自有Python子进程控制通过;连接失败/超时/取消保留前缀和半读,父任务中断结束自有进程组、封存非自引用清单。128读×4096行夹具约0.405秒仅证软件容量,不证手机网络延迟或指标准确性。当前正式首项0/5不变。来源方案/结果 · 不可变快照。
修复代码与实际测试包的关系 · 2026-10-17(E2)
- 问题表现:源码测试已通过,安装包仍可能是旧实现。先比较真实包内代码对象和已测主线,再判断是否真的覆盖;不以版本名或提交号代替包内来源证明。此次177仍是旧边界,固定10组合成Raw经真实二进制报告,旧包3组不符、私有候选10组符合,但没有新手机结论。
- 保守更新方式:整模块一致时才整模块替换;共享集成模块含其他已验证逻辑时,仅替换已审计方法、逐条证明其余字节未动。函数新增全局依赖须一起提供;本次旧录制入口需要time导入,因此使用已核完整主线模块。不是整个App已由当前main全量重构。
- 验证分层:包内代码、CLI和外置资源必须分别固定来源,缺条目不回退共享源码。源码文本断言在无源码包中记未评估,另做源码检查;包内可执行87项通过与源码1项通过分列。真实二进制合成回放、host Python加载包内代码、实际正常UI和手机E4分别报告,不相互冒充。
- 交付限制:私有ad-hoc核心只供本地诊断,不是签名App交付;严格Developer ID/覆盖安装/真实读界与固定五轮仍需完成。适用于本次自有包集成,不外推其他版本或物理启动精度。来源 · 快照。
签名阻碍、独立运行与UI就绪须分开验证 · 2026-10-17(E2/E3)
- 问题与机制边界:测试App的开发签名等待超时,不代表Mac Developer ID签名也不可用;按实际证书/目标/钥匙串访问分支核实,不反复重试失败私钥,也不将一次阻碍泛化到整条交付。此次Mac三次不同目标签名各一次成功,Lab原失败保留,根因没有据此确定。
- 来源与复现:以严格核同基座集成已审计变更,完整复制runtime;比较非范围模块/归档、GUI未签名字节、安装树与DMG解包树。清空源码路径环境并在独立目录运行实际二进制固定合成报告,才能说明包不依赖共享源码/旧安装链接。本次178十组合成符合,不外推真实手机或物理启动精度。
- UI判读:进程运行、正常打开返回成功,不等于窗口/采集入口已就绪。首次无窗口断言失败原样留存;一次正常“新建窗口”后只读核1窗口和未开始采集。恢复不是根因证明,也不是采集成功,不为使验收通过而删除失败或修改指标。
- 适用限制:内部Developer ID且未公证的包与正式分发分列;本次Gatekeeper未公证拒绝保留,未修改系统信任。Mac来源/安装/UI与手机测试App签名、参考资格、固定五轮分别关门,不以包签名代替E4。详见开发记录与不可变快照。
源准入与参考观察窗口的取证边界 · 2026-10-17(E2/E3)
- 表现与判别:采集Session能completed/durable、App真实启动,不代表所有指标已被武装。先查冻结CapturePlan是否请求该Registry指标及对应group、Raw是否存在相应源。当前资格轮startupEnabled=false、无lifecycle且startupReport=null,只能说明本轮没有启动观测,不能据此判产品数值错误,也不能在事后回填Raw或把missing写0。
- 参考工具限制:完整观察前缀与整个工具成功分别判。尾部剩余窗口短于实际服务耗时时再开始读,会因窗口限额取消;本轮35秒留存36完整读,尾读partial保留,不归咎设备断连。修复应先明确读前预算准入、完成覆盖尾界与未覆盖时段,再验证超时/取消/无重试负控;不能只延长超时、丢失败或按成功数补跑。
- 包内来源:唯一内部安装只重建已审计模块、核同非目标压缩模块与完整树,严格签名与独立cwd回放。179仅替换main已验composition,不代表整GUI/全部共享WIP由main重构;Developer ID未公证仍只作内部验证。
- 适用范围:上面属于准备/取证方法,不是L4真实数值或物理精度验收;正式五轮仍0/5。来源:完整开发记录与不可变快照。
有界参考的收尾准入 · 2026-10-17(E2)
完成至少一读后,若剩余观察窗口≤显式finishReserveSeconds,则不再派发新读,保留实际最后读界、endedBeforeWindowSeconds和stoppedForFinishReserve;这段尾部未被观察,continuousCoverageClaimed仍为false。CLI默认min(1秒,窗口),库兼容默认0。预留不保证查询必在1秒内返回,真实超时/取消/半读仍partial,不能用调度预算代替服务新鲜度或物理精度。66项软件与固定反例只证工具行为;正式L4真机五轮仍待。详见开发记录与软件快照。
运行观察与物理启动时间分层验收 · 2026-10-17(E4限定范围)
- 表现与机制:设备已进入运行状态,主机首次看到它仍可能晚一个或多个查询/调度周期。L4使用host请求→host观察,不是设备出生/首帧。五新轮为1335.465222–2018.404378ms,不能拿它减去另一时钟域的Total来判“差了多少”。
- 判断方法:保存每次精确应用双查询及进程列表完整读界,以至少两次未见作前置,端点须落在相邻同生命看见读的保守界;unknown保持unknown。Raw逐纳秒计算并核live/CSV/candidate及实际安装二进制副本生成的Observation报告,而不以同一执行器的自评代替独立复核。
- 固定门与范围:本批预先设定观察耗时0–5000ms(严格大于0)、参考单读≤1500ms/实际起始间隔≤2000ms、运行端点较首次完整看见结束的正向迟滞≤1500ms;五轮最差迟滞1193.615677ms。这是工程可用性门,不是行业物理精度标准;参考同源服务缓存新鲜度unknown,不能升级为真实出生精度或100%长期稳定。
- 文件名坑与避免:当前在线startup-report.json可为CoreProfile launch-trace schema;先核schema/algorithm再解释。L4由实时样本/CSV与显式startup派生报告承接,派生只在独立副本写入,不能覆盖封存源或拿Total冒充L4。界面无Running曲线是当前设计,不代表采集缺失,也不是恢复旧曲线的依据。
- 版本边界:179实际GUI受控CoreProfile路线已测;main较新官方启动GUI尚非本次已装执行字节,需后续整合验证,不据源码名外推已安装行为。前台/Total/九阶段、其他App/系统未由本批验收。详见合同/独立结果及不可变快照。
前台参考必须保留原字段 · 2026-10-17(E2,真机本项待验)
- 表现/机制:仅有同目标进程present,不能证明前台;字段缺失、None、0/1或字符串也不等于后台false。旧运行观测参考没有保留前台原字段,不能事后拿其五轮验前台指标。
- 判断/复现:沿用精确应用双查询与唯一列表身份,保留目标foregroundRunning;只有严格bool true/false派生前台/后台,其余unknown。每次完整读保留外层起止界,前台端点须由相邻同生命true读括住;unknown不当阴性、不跨生命延用背景界。假设与缓存新鲜度仍unknown。
- 避免/范围:新增投影不增加RPC/轮询;便携正负控检查缺失/非bool、身份跳变、unknown夹层、错误消费者与资源。软件95项参考及20项验收方法通过,不等于手机前台验收。前台是主机观察,不是业务ready或物理首帧;当前留存仍2/66。详见合同和实际软件结果。
采集通道与测试指令通道分层诊断 · 2026-10-17(E3,前台未验收)
- 表现:本批原生精确查询、列表和自有文件读取正常,Apple配方URL发送却12秒超时;同一“已连接”不代表两个控制通道都可用。
- 已证/未证:只读CoreDevice显示目标paired/wired/booted但tunnel connecting;不能仅凭该状态断言手机未解锁、线缆故障或产品数据Bug,根因unknown。前台字段缺失必须保持unknown,不能把进程present升级为foreground true。
- 判断与避免:分开记录每个通道与实际调用边界,资格失败必须保证Start0、封存失败、精确释放自有负载与句柄;一次只读后置核pending/run/进程,未见才说明本次无挂起负载。请求重连后另立新资格,不能自动重发旧run/覆盖partial或补拼前项五轮。范围仅本批环境与工具准入,不提升指标验收状态。详见前台资格增量及快照。
前台原始状态、参考读界与重复验收分母 · 2026-10-17(限定E4)
- 机制:进程present与foreground不是同义词;必须在唯一精确双查身份下读取目标原foregroundRunning严格bool。unknown不是后台false,也不能因为产品已有foregroundReady值而倒推参考true。旧运行五轮未保留该原字段,不能拿来重复验本项。
- 已验证方法:本次五个新生命、五Session,以请求前两次未见+相邻同生命严格true完整读界限定状态;Raw host差分/1e6逐值对齐live/CSV/真实安装程序副本报告。保持candidate、缺失不补0、不同生命/epoch不拼接。五新轮按先落盘的0–5000ms正耗时、单读1500ms/起始间隔2000ms/正向迟滞1500ms工程门通过,不是物理精度校准。
- 局限/避免:同服务独立读不等于外部物理仪器,新鲜度unknown;scene-active回调只作辅助。前台与运行可能同读同值,这不构成重复指标或Total证明。缺原字段、unknown夹层或URL资格失败都留partial;资格不入正式分母,失败不补轮。179特定路线的结论不扩至未安装的新GUI、其他App/系统。完整数值、失败和资源见本项验收及不可变快照。
版本历史增量:2026-10-28,普通报告不再混列host启动观测延迟,保留原始/诊断值及既有公式;E2展示修订。实施记录。