独立帧来源管理与默认全指标采集改造方案
1. 本轮任务、基线与结论
Owner要求:先制定详细方案;FTime激活与启动指标解耦;默认勾选所有当前满足采集条件的指标,包含启动与截图,用户明确取消才排除,尽最大能力采集。
本批唯一类型为devlog / plan,承担方案制定与实施准备,不代替独立指标验收。本批只交付方案与文档,不修改产品代码,不操作手机,不启动录制,不生成新App包。正式验收保持55/66、余11项暂停;Build234仍是原安装版本。方案状态partial表示尚未实现、资源及E4门开放,不是产品已具备新行为。
- 实施工作树:
/Users/itreenewbee/.codex/worktrees/perfowl-metric-comparison-20261028/perfowl。 - 分支:
codex/metric-comparison-round2-20261028;方案起点HEAD:58215dd7188b6a0816b2ad308fb5d5b20592a7ee。 - 本地main为
b64c1e46;不切换、不合并、不修改主工作树,不夹带未跟踪证据或其他设计文件。 - 延续首段缺失修复、第二轮采集合同及五项反馈修复,不覆盖历史结论。
决策摘要:独立帧来源管理器+设备级CoreProfile租约;全量采集意图减明确取消项+能力解析;运行与报告共用来源分段账本。不以删除一个条件判断替代生命周期改造。
1.1 已确认交互边界
Owner已明确回复:“下次测试生效,当前测试计划不变”。因此采集设置修改从下一Session生效,当前Session不变,界面明确提示;仅隐藏图表不改变采集。本批不增加运行中计划修订或即时停源功能,不设逐批Owner审批门槛。
2. 已核实的问题与影响(E1)
| 当前事实 | 影响 | 改造责任 |
|---|---|---|
capture_plan.py/scoped_feature_flags的frame_time要求同时存在startup和frame指标 | 不选启动时,持续CoreProfile帧路不可独立激活 | 从真实帧指标依赖解析独立需求 |
| 启动当前持有CoreProfile,并以Stop/drain再切帧配置续采 | 帧持续性依赖启动生命周期 | 设备级租约+独立frame owner |
| ActivityTrace projector收到白名单载荷即可置active,未要求有效帧间隔;reset不清该标记 | 无效首载荷可能遮蔽实际CP候选 | 健康状态替代存在性锁存 |
实时选源与离线frame_derivation.py的“存在AT记录则优先”不同 | 实时、导出可选择不同证据 | 共用source segment ledger |
WorkbenchMetricCatalog.defaultSelection仅10个历史默认组 | 默认排除了启动、截图及部分专用源 | 改为全量意图减显式取消 |
| group映射覆盖全部66个Registry ID;截图为附件而非第67项数值指标 | 有完整映射可复用,不能把附件混入验收分母 | Registry覆盖自动测试 |
| picker availability只有少量设备/准备/route字段,部分行准备后直接enabled | “可点选”不等于逐项能力已证明 | 引入能力账本,不直接全选enabled行 |
scopedCapturePlan在空选择时退回默认集合 | 全取消后可能意外重新采集 | 删除隐式兜底,明确空计划 |
screenshotCaptureEnabled = preview OR persist,controller再据此创建worker | 取消截图仍可能实际截屏 | 采集意图在服务入口强门控 |
| 当前选择主要是界面状态,缺少明确取消项模型 | 新设备、重连或恢复默认容易丢失语义 | 持久化排除集,显示偏好独立 |
源代码定位:Swift的WorkbenchModels.swift、CapturePlan.swift、PerformanceSessionController.swift、SessionStoragePolicy.swift、PerfowlWorkbenchView.swift;Sidecar的capture_plan.py、source_preparation.py、realtime.py、display_performance.py、frame_derivation.py。实施前重新核对准确符号与调用点,不依赖可能过期的注释。
既有证据只解释问题,不等于新方案验证:最近会话ActivityTrace有22499条消息但FrameLifetime匹配0;CP有427次presentation、425个interval、2个epoch,FTime覆盖25/58槽。历史CP某配置约18.76MiB/s,属于负载风险线索,不是本方案每台设备的实测流量。
3. 需求与边界
| 编号 | 必须满足 | 验收观察点 |
|---|---|---|
| R1 | 不选启动仍能独立请求FTime合适来源 | 启动off+FTime on具有独立生命周期 |
| R2 | 默认尽力采集全部已实现指标及截图 | 无取消项时66个ID都有请求或明确能力结论,截图独立记录 |
| R3 | 明确取消具有最高优先级 | 不启动该项专用服务、不计算或发布该项;共享源只保留其他指标所需部分 |
| R4 | 失败局部降级 | 一个源失败不阻塞其他健康指标及封存 |
| R5 | 来源可靠、可追溯 | target、clock、epoch、sequence有效后才有数值,不混算来源 |
| R6 | 资源有界、启动快、停止完整 | 预算、超时、并发、前后基准及失败回执齐全 |
| R7 | 旧数据不变 | v1 canonical/hash、历史读数/导出、原始文件SHA不变 |
不在本批实现Hitch、Hang、响应延迟或新的FPS折算,不将FTime倒数替换实际FPS,不改启动candidate.v9或Total设备时钟口径,不自动恢复暂停验收,不以截图作为帧真值。
4. 默认全指标:意图、资格和实际执行分离
4.1 唯一解析模型
定义Registry已实现集合R、用户显式排除集合X、截图意图S:
desiredMetricIDs = R - X
desiredScreenshot = not screenshotExplicitlyExcluded
eligibility = evaluate(desired, device/app/route/power/capability revision)
execution = eligible sources + bounded probes for pending sources
result = requested / excluded / collected / missing-with-reason
desired不因失败或暂不可用被删掉;eligible不是“本次成功有值”。report-only指标按其原始依赖派生,不逐项打开服务。已实现不等于正式验收通过,candidate仍保留candidate质量。
意图持久化为版本化CollectionIntent:policy=all-eligible.v2、标准化的excludedMetricIDs、screenshotsExcluded及preference revision。界面组取消映射成当前组全部真实ID;另存排除组ID,未来同组新增指标继承该组取消,避免升级偷偷恢复。迁移.fps/.frameTime到现有display组,显示折叠/隐藏偏好不进入排除集。
- 新安装:排除集为空;所有组意图on,当前有条件的组显示已选可采,待条件项显示已选待准备/条件原因。
- 旧设置:只迁移有明确“用户取消”证据的记录;历史低成本默认正选集合不推断成用户主动取消其他项。保留原设置备份和migrationVersion,只迁移一次,不每次启动重置。
- 暂不具备条件的行仍可取消采集意图,不能因为行灰掉而失去取消入口。状态标签与勾选状态分开。
- “恢复默认”清空明确排除,重新解析能力,不执行手机动作,不立即启动录制。
- 新指标、新设备能力、连接恢复不清空排除;Registry升级仅下一新Session纳入新ID。
- 全部数值取消、只选截图:v2支持
requestedMetricIDs=[]且screenshotsEnabled=true,不打开数值源;全部取消则Start不可用并提示“至少选择一项采集内容”,不偷偷恢复默认。
4.2 能力与条件账本
每个指标/附件至少记录:intent、eligibilityState、reasonCode、required/alternativeSourceIDs、依赖target/route/power、capabilityRevision、observedAt、generation。状态为eligible / pending / unsupported / not-applicable / temporarily-unavailable / failed / resource-limited / user-excluded,严格区分能力、适用性、采集故障和人为取消。
| 条件 | 处理规则 |
|---|---|
| 尚未选择设备或目标App | 保留默认意图;依赖该条件的项目pending,不凭空判unsupported |
| 服务/字段能力已确认支持 | eligible,按源依赖合并执行 |
| 只有设备在线、版本或route线索 | pending,使用有界准备,不把UI enabled当证据 |
| 明确不支持的系统/服务/schema | unsupported,保留依据;不周期重试 |
| 一次连接/查询失败 | failed或temporarily-unavailable,不永久写入unsupported缓存 |
| 能耗/电池有真实电源与通道前提 | 分别核对;无线route不等于未充电,缺电源事实就pending/missing |
| GPU Counter/thermal等专用源 | 采用真实能力结果,不能以prepared统包支持 |
| 启动在观察现有进程模式 | 本次not-applicable,保留请求意图,不伪造冷启动 |
缓存以设备连接generation+系统/服务schema+route+target+power revision为键;连接、目标、route/power变更触发相关节点失效,不对每条sample全量探测。明确unsupported在当前generation/schema内缓存;失败仅允许下一次用户Prepare/新连接重新探测,不形成后台重试风暴。动态电源条件更新来自已有状态事件/原有低频采样,不增加高频轮询。
Session冻结的是用户意图和策略版本;能力解析是独立有revision的运行账本。Session内条件恢复,可启用冻结意图内的来源,记录准确启用时点与首点warmup;不回填此前缺口。不将能力变化伪装成用户修改计划。若共享源不支持安全重配置,本Session明确deferred-to-next-session,不重启整个采集器。
4.3 逐类采集依赖清单
下表取自当前ios-platform-profiles.candidate.v1.json/metricSourceContracts,是现状基线,不是已完成v2改造或全部E4可用的承诺。P0应产出逐ID的machine-readable allOf/anyOf依赖表及资格测试;表内固定数量由Registry一致性检查锁定。
| 当前family / 数值ID数 | 当前adapter | 新计划执行与资格要求 |
|---|---|---|
| sysmontap / 14 | pmd3.sysmontap.raw | 合并CPU/内存/核心/线程/调度/磁盘依赖,process字段要求有效目标,device字段不因目标暂缺一并失效 |
| device-network / 2 | pmd3.device-network.raw | 核对设备网络服务/计数器;首点差分warmup |
| process-network / 2 | perfowl.process-network.raw | 要求有效目标与流量归属,不拿整机替代 |
| graphics / 3 | pmd3.graphics.raw | GPU各字段分别验证,某字段缺失不整组填0 |
| display-performance / 5 | pmd3.activity-trace.frame-lifetime.raw | FPS、FTime、P95、refresh、jitter细分依赖;Graphics FPS实际备选关系须与runtime逐ID对齐,不照抄family代替执行图 |
| gpu-counter / 1 | perfowl.gpu-counter.raw | 设备/服务/可解码counter schema资格,专用源按需启动 |
| core-profile-frame(legacy名称) / 14 | pmd3.activity-trace.frame-lifetime.raw+perfowl.frame-pipeline | 当前为AT派生,不因名称含CP就声明已支持;新FTime替代源与分段统计资格显式增加,不偷改旧reader |
| energy / 7 | pmd3.energy.raw | 目标、服务与各energy字段可用性,不把source-native cost当物理功耗 |
| device-conditions / 6 | pmd3.device-condition.raw | 电池/温度/thermal分字段、通道和电源条件,零/负哨兵沿用各自合同 |
| startup / 12 | perfowl.lifecycle.passive.raw、pmd3.core-profile.raw、perfowl.startup-control.raw | 2项host observation与设备时钟Total/阶段区分;依赖图按ID拆解,不要求每个ID都依赖全部源 |
| screenshot附件 / 不计数值ID | 现有Swift screenshot worker | 单独截图能力与总开关,保留1Hz/JPEG策略 |
4.4 启动与截图的副作用
默认选启动不等于在连接、Prepare、勾选时启动/终止App。只在用户明确按Start且所选启动模式要求时执行现有受控启动;界面在Start前说明该模式会重新启动目标。观察现有前台模式不为了“尽力全采”擅自切App、杀进程或制造一次启动。AI在本方案阶段不执行手机动作。
截图统一以CapturePlan.screenshotsEnabled为实际采集总开关:默认采集且保存序列;preview仅决定展示,不反向开启截屏。选中截图但关闭preview仍保存;取消截图时worker、设备请求、JPEG编码、预览刷新及落盘均不启动,已完成历史文件不删除。兼容CLI、prepared及普通Start三条入口,includeScreenshots和旧storage policy不得覆盖显式取消。保留既有1s网格、异步有界编码与JPEG策略,本批不提高频率。
4.5 共享源与禁止采集的精确定义
共享Sysmontap/ActivityTrace可能随其他已选指标返回附带字段。取消项不再申请专用服务、添加专属字段、派生、发布或进入指标导出;若底层支持字段裁剪,应裁剪。底层不可拆的原生共享消息可以随所需源保留在原始证据中,记录incidental,不宣称线上绝不收到一个相关字节。源以消费者引用计数管理,取消FTime不能停掉仍被P95/refresh/jitter或其他指标使用的AT。反之无消费者时应停止专用源并取得stop回执。
5. 独立帧源架构
CollectionIntent + Registry + CapabilityLedger
|
frozen CapturePlan v2
|
metric dependency/source resolver
| |
normal shared sources FrameSourceManager
| |
shared ActivityTrace CoreProfileLeaseCoordinator
| |
startup owner frame owner
\ /
FrameSourceSegmentLedger
|
realtime / sealing / report / export
5.1 组件与合同
FrameDemand:由真实依赖解析needsFTime / needsATWindowStats / needsFPS,报告帧统计依赖也计入。只要需要FTime/其指定帧派生即能独立请求帧路;FPS-only不自动开启CP。依赖图明确allOf、anyOf、可选补充源,不能再以prepared sources任意一个交集代表全部准备。FrameSourceManager:生命周期start / onSourceEvidence / onFailure / onLease / stop;单写者任务处理状态转换。状态及事件带generation、epoch、planHash;过期回执丢弃并计数。CoreProfileLeaseCoordinator:同设备generation最多一个kperf/CoreProfile录制owner。startup和frame提交请求,串行执行configure/start/stop/drain/lease release;不创建两个互相覆盖的tap。FrameSourceSegmentLedger:增量追加来源选择和质量证据,live与offline共用。不得以某来源是否出现过一条raw数据决定整个Session来源。
frame-only配置复用现有launch_trace.py的帧模板构造,订阅PresentedFrame所需的最小已证过滤,不默认使用完整启动过滤或全量kdebug。现有subclass与exact-debug-id配置应分别保留版本/filters/config hash,并以同场payload、raw和覆盖比较;exact过滤也不能仅凭过滤名就宣称低流量。未证明更优前不顺带变更startup C0模板。
新增模块可采用frame_source_manager.py和coreprofile_lease.py,名称实施时可调整并记偏差;避免整体重写realtime.py。共享AT复用已有订阅,不为FTime重复开同服务。
5.2 默认选源与健康状态
初始优先ActivityTrace FrameLifetime;这是兼容当前路径的决策,不是已经证明所有设备最准确/最轻的结论。CoreProfile PresentedFrame为独立候选路线,不以是否勾选启动作为资格。
健康状态:idle → subscribing → observing → healthy;错误可进入degraded → fallback-pending → healthy(candidate)或failed/resource-limited。healthy建议资格为同target/clock/epoch连续3个有效相邻interval;此阈值是待测策略,不增加3帧均值,不把第1/2个合法值删掉。首次有效数值可在健康资格完成前按既有质量输出,subscription-active与numeric-valid分开。
- 收到消息、白名单匹配、首个孤立结束点都不是有效间隔证明。
- 静态界面无新帧不自动判坏;无运动证据时保持observing/idle-without-evidence并呈现missing,而非0。
- 明确连接、订阅、schema、时钟/身份错误可触发一次fallback。
- 默认全采包含FTime时,8s观察后若AT尚未资格化且CP能力与资源准入成立,可做一次有界CP资格探测;原因是“AT证据不足,探测候选”,不是判定静态场景丢帧。若有已有动态活动线索,可提前进入该调查;线索本身不派生FTime。
- 探测得到至少一个合法CP间隔后可选择CP candidate段;8s内静态无间隔只结束首次资格等待,标记observing/insufficient-evidence,不凭无帧判源坏。若订阅、schema、时钟及资源准入成立,CP可继续有界接收,等待后续真实帧,不因静态首屏使整场后续FTime失效;停止条件是用户Session结束、源错误或明确资源超限。该持续观察资格须经P3资源门验证,未验证的配置只开放显式受控诊断,不宣称默认持续能力。
- 一旦本Session选择CP,晚到AT不自动抢回,防止来回切换;仍可保留AT供其他指标。AT已健康则不保留多余CP frame录制。
- 每generation最多一次自动向CP降级/探测,不能因消息抖动重开generation规避上限;真实重连才重置。重连还须遵循上层已有退避与次数上限。
5.3 与启动并存
| 启动 | 帧需求 | 行为 |
|---|---|---|
| off | off | 不申请CoreProfile;FPS及其他已选源照常 |
| off | on | FrameSourceManager独立运行;AT优先,必要时独立CP资格探测/续采 |
| on | off | 仅现有startup owner,完成后释放,不转帧 |
| on | on | startup初始窗口优先持租约;其Stop/drain完成后frame按需求接管 |
启动完成后不为帧重复launch目标;frame等待租约期间其他源继续,不用host时间填补空档。startup失败/取消也必须释放租约;若停止未确认,标记lease-quarantined并阻止新CP启动,健康源继续,禁止两个owner赌并发。启动期间若AT已健康,frame无需接管CP。中途不得用启动需求抢占已运行frame并偷偷重启App;另一次受控启动是新Session或后续明确支持的操作,不在本批实现。
6. 指标公式与质量合同(先入档,实施不改公式)
FTime metricID为ios.frame.time,scope为foreground-device,Registry unit为milliseconds(界面/公式以ms表示),保留候选来源/归属边界,不包装成目标进程逐帧物理真值。
6.1 ActivityTrace FrameLifetime
沿用display_performance.py现有条件:前驱严格衔接prev_mach == last_end_mach,同一身份/epoch/display/foreground,refresh interval有效。
delta_ns = ((end_mach - prev_mach) * numer) // denom
FTime_ms = round(delta_ns / 1_000_000, 6)
首点warmup;不相邻/非正/乱序点不输出正常值;大于12个refresh周期按既有source-gap语义处理,不称为确认丢帧。具体raw字段schema、时钟桥和关联键沿用现有解析器及Canonical指标页,实施前以固定fixture锁定。
6.2 CoreProfile PresentedFrame
沿用frame_derivation.py的PresentedFrame debug ID 0x31800318:
timestamp_ns = (mach_ticks * numer) // denom
FTime_ms = (timestamp_ns - previous_timestamp_ns) / 1_000_000
相同epoch内相邻有效presentation成对;首点warmup,非递增点为out-of-order;继续candidate。CP的设备/连接/配置身份校验不能冒充逐帧目标进程归属;若原始事件未携带可证明的归属,继续foreground-device及candidate边界,不把租约配置目标当作每帧target证明。该路径“先每点转ns再作差”与AT“先差再转ns”可有取整差异,本批不合并公式或宣称精度等价。
6.3 分段和缺值
每次切源/重连/时钟或归属变化均开启新epoch,清前驱,首点warmup。禁止跨来源、epoch或身份作差;不回填/插值/用FPS倒数补FTime;missing与合法0仍按各指标原合同。CP FTime不得替代AT专属P95/refresh/jitter,缺独立证据则这些指标missing;不把CP间隔同时算成另一个源的重复帧。
Ledger逐段记录sourceID / generation / epoch / start-end / reason / identity-validation / clock / algorithmVersion / candidate / gap / counters;引用有限诊断而不是复制原始载荷。新实时、封存、CSV/Excel统一按已选段读数。跨AT/CP等价性门未关闭前,不生成混源整段帧统计:可按来源段展示,现有汇总留空并保留原因;单源完整段沿用既有统计。普通报告维持既有面向用户的简明表现,诊断/raw保留全部证据,不把内部字段堆到用户主界面。
旧Session无ledger时走版本化legacy reader,保持历史公式与结果,不用新策略重写历史原件。新旧算法版本和source contract先更新唯一Canonical指标知识页,再进入代码;不新建一串版本知识页。
7. CapturePlan v2与跨语言迁移
选用schema v2,不原地改变v1 canonical/hash。Swift/Python继续支持v1读取与原hash;新Session写v2,sidecar握手明确支持版本,旧sidecar遇v2返回版本不匹配且提示更新,不偷偷降成不同语义计划。
v2保留requestedMetricIDs为冻结desired数值集合,保留startup/screenshots显式布尔及Registry hash;新增selectionPolicyVersion、intentRevision、标准化excludedMetricIDs/excludedGroupIDs、frameSourcePolicyVersion。完整字段表、缺省、canonical排序、枚举及null规则在P0先以Swift/Python共享golden JSON冻结。排除字段与requested集合冲突直接拒绝;unknown ID不默默丢弃。
能力结果和动态来源账本不进冻结plan hash,独立保存并引用planHash、capabilityRevision及epoch。startupEnabled须与请求启动ID一致;截图单独开关,不由storage preview反算。v2允许截图only空数值集合;v1保持非空合同。制品reader和导出器按schema分发,canonical hash测试至少覆盖v1原golden、v2完整/截图only、乱序/重复标准化、非法冲突、unknown版本。
8. 性能、资源、并发和超时门禁
以下均为实施目标/拟定门槛,非实测通过值。P0先测同规模基线,若既有实际chunk上界与拟定限值冲突,须在代码前追加原因与预算决策,不能直接扩大无界队列。
| 项目 | 设计和门槛 |
|---|---|
| 解析复杂度 | 意图/依赖解析每revision一次O(M+E),M当前66;消息分发摊销O(1),只对新增事件顺序解析;不逐帧hash、全量回扫或探测 |
| 并发 | 每设备1个CP租约owner、1个状态写者;复用AT/现有后台decoder;DTX控制操作串行;无逐指标进程、无新增高频轮询 |
| 准备 | 沿用每源3s、总12s运输准备边界;准备仅验证服务/能力,不隐式开启重型采样。首次数据观测在采集阶段异步执行,不阻塞其他源ready |
| 帧资格 | AT观察8s;CP探测观测8s,configure/start总5s;独立帧fallback决策至完成/明确失败目标≤20s(不含等待startup租约);到时取消并记录,不循环重试 |
| 启动占有 | 沿用当前startup等待15s、drain4s、帧重启5s上界,实施先核对入口总截止;必须另列排队+启动+观测的累计最坏路径,不把20s宣称全Session上限 |
| 停止 | frame stop/drain≤4s,租约未确认停止进入quarantine;任务取消后跟踪残存worker,不当作已成功退出;原始证据/封存继续按既有边界 |
| 内存/队列 | 管理器常驻增量目标≤2MiB;原始队列同时限制count和bytes,拟定总64MiB、单chunk32MiB,超过显式source-gap/resource-limit;不复制Base64或整份raw |
| 避免阻塞 | 控制状态转换p95<1ms(不含I/O),主线程新增工作单次<16ms;高流量解析与截图编码不占发布主通道 |
| 同负载回归 | 相同选择/相同raw/保留策略下,总CPU时间和处理耗时≤基线1.10倍;峰值RSS增量≤max(16MiB,基线10%);首点及Stop p95退化≤max(100ms,基线10%) |
| 新默认成本 | 单列“旧默认→全默认”的实际新增源、CPU/RSS/I/O/带宽/启动与停止成本;不将新增工作量与管理器同负载回归混为一谈,不以降低采样/丢弃证据掩盖超标 |
上述阶段保守串行合计上界:运输准备12s+AT资格观察8s+租约等待最多19s(startup 15s+drain 4s)+fallback完成20s=59s;实际阶段可重叠,但不以重叠保证更快。租约等待到期记录deferred/lease-unavailable,其他源不等待;此数只约束该控制链,不包含用户外部操作及既有封存阶段。实施须同时测全Session首响应与结束耗时。
默认尽力不是无限耗资源。实际超预算时只停止问题专用源,标注resource-limited、已收字节与时间,保留用户意图,不伪装不支持或用户取消;所有其他健康指标继续。持续CP默认策略开放前,必须有同设备受控场景资源比较;若仍接近历史高流量,不将它描述为轻量持续采集,也不以静默关闭FTime交差。
流量同时区分DTX服务接收payload bytes、raw写盘bytes、实际USB/网络链路bytes。前两者可内部计数,链路测不到则明确未测,禁止用payload冒充线速;报告MiB/s、MiB/min和预计小时量,区分derived-only/full raw及截图。截图按实际JPEG尺寸×实际成功张数统计,不预设固定压缩比例。
8.1 基准矩阵与执行时间预算
- 同一固定raw分别运行baseline与candidate,各3次,报告中位数、最差与原始收据。样本覆盖60s、1h、4h时间跨度及60/120/240事件每秒重放;离线加速重放衡量吞吐,不冒充连续4小时内存稳定。
- 最坏输入覆盖既有真实最大CP chunk、stackshot与截图JPEG并发、发布1Hz、source错序/断连/stop;记录首响应、长任务完成、p50/p95/max延迟、CPU、RSS、队列峰值、落盘量和missing/drop。
- 管理器单测/契约测试目标分钟级,聚焦回归预算≤10min,全量回归按当前实测基线单列;每个基准子进程最长120s、批次最长15min,超时保留失败回执,不自动反复重跑。
- Owner许可的新鲜E4分静态前台基线、受控动态、长稳各组,比较AT-only、CP-only、自动策略及全默认;阶段性计划15min、1h、4h实时时长,不在本方案阶段执行。AI不自动滑动/切App。
- 测试前磁盘≥10GiB且≥预计新增量两倍;按实际接收率预测下一检查前增长,预计触线就提前停止新采集。首次、每批后、持续期间每30min检查;保留raw/失败证据,不按年龄删除。
9. 实施拆分、文件范围与交付物
| 批次 | 主要修改 | 交付与进入后续条件 |
|---|---|---|
| P0 合同与基线 | 逐指标能力/依赖表、v2 golden、FTime公式/选源版本、同规模基准 | 文档先行;锁定baseline;落实已确认的下一Session交互;不以基线已有失败当新增回归 |
| P1 全量意图与入口 | WorkbenchModels、CollectionIntent、CapturePlan Swift/Python、selector/view、controller、SessionStoragePolicy | 默认全意图、显式取消、截图only、prepare/普通/CLI一致;能力原因完整;截图关闭真实零请求 |
| P2 独立帧与租约 | FrameDemand/Manager、CP coordinator、startup/frame owner、source_preparation/realtime的窄接线 | 四组合均有软件证据、独占与停止完整;CP-only显式可测,先不宣称自动策略E4可用 |
| P3 健康/有界降级与账本 | display projector状态、fallback、source segment、frame_derivation及报告导出 | 运行/离线一致,首无效AT不遮蔽CP,不混源;资源门通过后开放自动策略 |
| P4 软件/制品/Owner复测 | 匹配单测、回归、基准、签名/打包验证和文档闭环 | 真实包与当前源核同、Owner新会话E4;Lead独立验收,不自评阶段PASS |
上述P0–P4是本改造子批次,不改变站点总阶段P6。各批实际修改、偏差、测试、剩余门追加到本文带日期Implementation/Validation Update;不写“代码完成”等于指标验收完成。无批量全目录重构,不改Hitch与其他指标公式。
10. 必测矩阵
| 类别 | 用例与预期 |
|---|---|
| 默认 | 新安装/恢复默认覆盖66个Registry ID意图,截图on;report-only正确依赖,无第67项数值 |
| 资格 | 未连设备、未选App、准备成功、能力unknown/unsupported/failed、route/power变化;不将nil当成功 |
| 排除 | 取消各组/单项、重连、重启、升级新增同组ID、恢复默认;排除持久,不被capability刷新清掉 |
| 空选择 | 数值全关+截图on合法;全关Start禁用;无默认回退 |
| 截图 | 选中/取消×preview开/关四组合;普通/预热/CLI入口;取消时device request/worker/encode/write全0 |
| 启动副作用 | 勾选/Prepare无launch;Start观察模式无冷启动;用户明确冷启动才执行现有动作 |
| 核心四组合 | startup×frame各on/off,frame-only可独立CP;startup-only不留frame录制 |
| 需求 | FPS-only、FTime-only、P95/refresh/jitter-only及所有display;不误开CP、不借CP伪造AT数据 |
| 健康 | 首AT载荷无interval、wrong identity/timebase、后续有效interval;健康不由消息存在锁存 |
| 静态/动态 | 静态无帧不误报丢帧;最多一次资格探测,静态转动态仍可产帧;资格等待到期不阻塞其他源,资源超限才局部停止;动态线索不派生帧真值 |
| 切换 | AT错误、CP不支持/失败、CP晚成功、AT晚到;一次降级、不振荡、不交叉作差 |
| 租约 | startup正常/异常/取消/stop超时;等待与drain间无双owner,未确认停止quarantine |
| 重连 | 新generation重建,旧回执不污染新会话;不由普通消息制造generation |
| 共享源 | 移除一个消费者不误停其他人;引用数归零释放;shared incidental明确,不额外派生取消项 |
| 连续性 | epoch首点warmup、乱序、缺口、重复及大chunk队列上限;missing不变0,不延长TTL掩盖问题 |
| 计划 | v1/v2 Swift/Python golden及hash核同,截图only空ID、非法冲突/版本/unknown,能力revision不改planHash |
| 输出 | live、封存、普通报告、CSV/Excel逐槽同源;混源整段统计按合同留空/分段,不重算旧Session |
| 部分失败 | 任意专用源失败健康源照采、正常封存;全部来源失败有明确结果不假装成功 |
| 成本 | 相同源回归与全默认新增成本分开;60s/1h/4h重放及实时长稳分开;所有超时留痕 |
| 原件 | 现有封存Session/raw逐文件SHA未变,无无关WIP进入提交,无设备身份进入公开文档 |
当前回归参考:最近Python/native3097项有1失败、1错误已在旧基线复现;Swift438项、12skip、0失败。实施前复跑匹配范围并固定错误签名;语义改变导致旧默认选择断言失效,应按新合同更新对应断言,不删测/跳过充绿。与本批无关的原始数据失败单列,不擅自扩修。
11. 回滚与验收门
- 以版本化selection/frame policy开关隔离新策略;回滚不删除排除偏好,不把用户取消项复位,不重写既有Session/raw。
- App与Sidecar必须同版本交付;回退旧包时恢复对应policy reader,必要回滚保留私有目录,不并行安装第二个标准App。
- 自动策略资源或正确性门失败:保留独立frame和诊断证据,不静默宣称完成;局部停用新策略并在实施记录给出修正决策。
- E1设计/静态、E2软件/制品、E3环境、E4新真机分别报告;正式55/66与剩11项不由本批软件结果自动更改。
- 产品实现交付按AGENTS要求窄提交、双远程同SHA、签名/公证/staple/Gatekeeper、独立安装与SHA;延续Owner既有公证暂缓指示时明确partial,不声称正式可分发。GPL门保持独立,不由公证代替。
- 标准安装只在
/Applications/Perfowl.app,先确认实际空闲退出。当前方案交付不换包、不安装。
12. 文档、发布与执行交接
本批计划登记时间线及handoff,新增不可变HTML快照;仅描述计划,不修改知识库、首页指标计数或55/66状态。实施涉及公式/来源/质量变更时,同批更新唯一Canonical指标页、知识总览、首页及C1–C7联动,先文档后代码。生产发布遵守来源权威门,不从feature/WIP绕过发布保护。
下一Implementation执行指令(计划文档先行;不表示独立验收已通过):
> 在本任务metric-comparison工作树,以58215dd7及本方案文档提交为基线,按本文P0→P4顺序实现“独立帧来源管理+默认全量意图减用户排除”。先冻结v2合同、能力依赖及基准;所有服务入口遵守排除,截图preview不得反向开启采集;startup/frame共享独占租约,live/report共用分段来源。按Owner已确认的下一Session生效,不擅自实现运行中计划修订。不扩至Hitch/Hang或其他公式,不操作手机,不恢复11项验收、不碰原主树或无关WIP。每批在本文追加实际修改/偏差/验证/遗留,返回窄提交与双远程状态、基准和测试收据、真实制品/签名状态及Owner复测步骤;自测结论不代替Lead独立验收。
13. Validation Update · 2026-10-29(方案批次)
已重新核对工作树HEAD、main ref、源代码核心门控及默认集合,保留所有原有未跟踪文件。本批尚无产品实现或新真机证据。
- 源码Registry与group映射独立提取核对:66/66,缺失0;FTime真实ID为
ios.frame.time,Registry单位milliseconds,已与公式段核同(E1)。 - frontmatter、状态词表、代码围栏、文内已有来源链接及本批隐私模式检查通过,
git diff --check通过。Owner“下次测试生效”已写入,不留待定交互分支。 - 固定Node24.19.0执行
npm run build:66项知识合同门通过,仍有44项既有内容风险提示;client阶段完成,server阶段耗尽180s总预算。超时后进程组检查又报PermissionError/EPERM;本次站点完整构建未通过,未到render/全站死链终验,不拿历史构建成功代替。 - 后续进程检查未发现本批site worker继续运行,磁盘约12.77GiB可用;未清理证据、未扩大构建预算、未扩修构建器。公开站点未部署;后续空闲时按既有受控命令复跑,构建和来源权威门通过后再发布。
- 原始构建日志在本批私有
.local-evidence/independent-frame-plan-20261029/site-build.log;HTML初始方案快照保留,验证结果另新增快照,不覆盖旧归档。文档可供实施准备,网站交付状态partial。提交/双推/通知以实际交付收据为准。
14. Implementation Update · 2026-10-29(Owner已下达实施指令)
Owner要求开始实现、测试、打包并覆盖本机。当前Implementation角色在c6ba3883继续,同一AI顺序执行,无子代理、不操作手机;Hitch保持后续待办。当前状态partial,尚未宣称完成或正式PASS。
P0先冻结:实际新Session写schema2,v1公共兼容工厂/旧golden保持原语义;新字段为selectionPolicyVersion=all-eligible.v2、intentRevision、excludedMetricIDs、excludedGroupIDs、frameSourcePolicyVersion=independent-frame.v1。v1字段及hash不变,v2校验unknown/冲突/截图only,能力与source segment不进plan hash。FTime两条原公式不改;每代最多一次CP备选,CP持续接收按字节/速率预算有界,不把未知归属升格成process。
已保存当前core源码与CLI基线,旧capture-plan七项软件测试通过。当前可用空间接近10GiB底线,构建前重新核对可重建缓存及预计新增量,证据不删;实际资源/E4与公证门保持独立。后续实际范围、偏差和结果继续追加本节。
14.1 执行修正(实施前口径补充)
Direct入口保留原始CapturePlan不变,另传实际执行ID与启动模式。官方启动已在Swift侧执行/失败时,Sidecar仅保留外部观察,不得因重新读取原计划再次启动CoreProfile或二次launch;只允许从执行集删除已外置的启动阶段ID,不允许扩大采集。报告仍保留这些请求及缺失原因。资源保护统计实际payload字节,不把chunk缺失的byteLength当0;每代32MiB单chunk、5s滚动20MiB保护阈值仅为保守软件预算,非USB线速或E4结论。
当前磁盘约7GiB,已暂停新测试/构建并告知Owner;其他项目的临时目录全部保留。新增测试需按新截图合同显式选择截图:选中即保存,取消时预览也不请求;旧preview-only Session读取兼容不变。
14.2 资源门保持关闭
按§5.2/§8/§11既定约束,新增独立CP自动录制在真机同设备资源门前默认关闭;显式诊断开关PERFOWL_INDEPENDENT_FRAME_SOURCE_DIAGNOSTIC=1才允许frame owner打开新录制。默认全选意图、AT路径、分段账本仍生效,已存在的startup串行帧续采保持兼容并受预算约束。不把软件基准代替真机持续采集成本;默认自动策略启用须由Lead后续确认,不能在本批自我放行。
能力账本区分运输prepared与numeric eligible,逐ID allOf/anyOf依赖、排除项、revision和source generation入档;未知电源/启动能力与GPU/thermal条件显示待验证,不以无线或prepared替代实际数值证据。
14.3 实际实现与边界 · 2026-10-29
- Swift新增
CollectionIntent.swift(版本2、持久化排除组、revision),新Session默认17组、66数值ID及截图附件;未知未来组不清空已知排除。选择修改只进入下一Session。全取消拒绝Start,截图only合法;原includeScreenshots、preview和旧storage开关均不能恢复显式取消。截图选中即保存,取消时预览与worker也关闭。 CapturePlan.swift/capture_plan.py保留v1 canonical/hash,真实新Session显式v2;完整plan穿过prepare、Start和direct CLI。direct原始请求不变,实际执行仅允许删去Swift已外置的启动项;observation-only不打开CP。准备中重绑使用最新configured计划;Start的截图only空集合仍覆盖原准备计划,不能因空tuple跳过。- 新
frame_source_manager.py合并manager、CoreProfile lease及分段账本,避免新增一个小模块;AT三个有效同上下文衔接间隔资格、一次CP备选、停止未确认quarantine、分代原子账本。32MiB单chunk与5秒20MiB保护统计实际payload,未知size不记0;这些是软件保护值,不是实测USB线速。AT同上下文资格后短路重复资格算术,逐帧数值仍由原display decoder验证;上下文变化或明确源错误才重新资格化。 realtime.py接线独立dedicated帧通道;startup stop/drain后释放租约,再串行续采,不二次launch。新独立CP录制默认仍受§14.2资源门限制;AT晚到不抢回已选CP。AT已健康的冗余CP在下一交付chunk时停止。观察8s、开通5s、停止4s保留独立截止。display_performance.py无效首载荷不锁active、reset清active。online_report.py/frame_derivation.py共用选源账本,换段warmup,逐段统计、索引namespace与checkpoint恢复;仅真正有interval的多源才把全局混合统计置空,不把来源切换误当全场同源。- 新
collection_scope.py统一数值wire与报告输出白名单;metric_engine.py/report_engine.py的v2在线、离线数值也遵循requested IDs。单FTime/P95请求不顺带发布其他帧统计,缺值不填零;v1读取语义保留。原始共享证据中的incidental字段不冒充已选指标。
相对方案未闭合部分(明确partial):逐ID依赖allOf/anyOf、transport prepared与numeric eligibility分离已实施;完整动态capability/power revision、缓存失效与运行期恢复账本尚未全面落地,当前未知条件保守显示待验证,未接入的能力不得标eligible。共享raw投影仍可能执行附带算术后再过滤,尚不满足“取消项绝无内部计算”的最严格版本;本批保证其不发布、不持久化数值及不为取消项额外开专用源。全默认新增源的实际USB/网络、CPU/RSS/I/O和动态场景成本未实测;因此不宣称完整资源门或默认独立CP持续策略已完成。Hitch仍仅待办,55/66与余11项暂停不变。
14.4 软件验证进展 · 2026-10-29
空间由Owner清理后恢复至约19GiB,AI本批未删除其他项目文件。软件测试与打包继续分别核容量;本批不启动手机动作。
已取得:共享v2 golden与截图only、原生Swift全部(排除独立OCR挂起项)443项、12skip、0失败;截图停止worker隔离3次均0失败。OCR单独60s截止仍挂起,保留Vision semaphore调用栈,未修改产品或放宽断言掩盖;不是完整Swift全绿。准备中替换计划与prepared截图only、单ID取消报告等37项窄回归0失败。完整Python原生回归与资源对照、制品/安装结果继续以下方实际收据承接。
首次未装载native codec的Python全量3121项得到20失败/7错误/81skip,不能与生产环境基线比较;保留原日志。已分别识别未装载native、旧帧需求/取消输出断言、v1 trace gate兼容和负载敏感项目,按真实新合同修正测试、恢复v1兼容;不把其中全部归为旧问题。后续使用当前ABI native codec重跑,与上一批正式环境3097项1失败/1错误逐签名比较。
14.5 同规模加速重放对照 · 2026-10-29(E2,非设备流量)
保留改前core源码,使用相同生成的decoded FrameLifetime消息,前后各3次、交错顺序。覆盖60s的60/120/240Hz、1h的60Hz、4h的60/240Hz时间跨度;最大每次3,456,000条事件。每个子进程120s、批次900s边界,不改变采样频率或丢弃事件。
| 模型跨度 / 频率 | 投影路径耗时中位数 后/前 | CPU时间中位数 后/前 | 峰值RSS差值 |
|---|---|---|---|
| 60s / 60Hz | 1.084 | 1.088 | -2,469,888 bytes |
| 60s / 120Hz | 0.941 | 0.960 | +278,528 bytes |
| 60s / 240Hz | 1.050 | 1.052 | +151,552 bytes |
| 1h / 60Hz | 1.063 | 1.056 | +192,512 bytes |
| 4h / 60Hz | 1.042 | 1.047 | +126,976 bytes |
| 4h / 240Hz | 1.090 | 1.099 | +163,840 bytes |
上述是RealtimeMetricProjector.consume/snapshot与manager的内存模型,不含DTX解码、完整磁盘/报告封存、截图、系统启动或实际USB。4h/240Hz前后中位数45.632/49.717秒,candidate最慢59.760秒,最低57,831事件/秒;六组中首响应最慢0.383ms、内存模型Stop最慢0.447ms,不把它冒充真实Session Stop。block I/O计数仅代表该模型未持久化,不声称真实I/O为零。各组中位数满足此窄路径1.10倍与RSS预算,但单次最慢值、完整任务延迟分位数和真实长稳仍须单列。
独立display+manager微基准也保留:4h/240Hz后/前中位数1.260,超过1.10;不能用全路径分摊后的比例隐去该局部开销。第一次探索运行曾与其他回归并发且跨优化点,独立保留,不计最终同版本比较;最终两组基准顺序执行。全默认新增源、最大CP chunk/stackshot/JPEG并发、队列峰值与实机带宽未纳入这些结果,完整资源门仍partial。加速重放不等于4小时真实运行;此证据不开放默认独立CP自动录制,也不新增E4。
14.6 最终原生环境回归 · 2026-10-29
当前Python3.12 / pymobiledevice3 11.3.1 / 当前ABI native codec环境,完整发现3123项,0失败、1错误,226.815秒。唯一错误是test_online_positive_and_identity_mismatch_negative_are_separate (bound=False)的Raw adapter host monotonic回退,与上一批基线独立复现签名一致,原失败证据保留;本批不改SW1实验语义来消掉它。不能称全量全绿。
前一次同环境3121项为1失败/1错误,其中subscription pump吞吐19,222事件/秒未达20,000门槛;旧树与新树各独立3次均通过,最终完整回归亦通过,保留负载敏感记录、不改阈值。最终新增入口/CLI/prepare重绑/截图only/单ID输出等聚焦93项0失败,9.348秒。旧startup-only需求断言按已批准的独立帧合同更新;v1假ID测试的trace gate兼容已恢复,不将v2约束错误套给旧入口。Swift443项(排除独立OCR项)、12skip、0失败以及OCR超时仍分列。
软件源码176文件在最终回归/构建前冻结SHA,当前无漂移;后续包要核Swift源码、Python冻结code object、独立挂载树与安装树,不以构建退出0替代制品核同。构建/安装与网站状态见下一增量,当前仍partial。
14.7 Build235制品与覆盖安装 · 2026-10-29(E2/E3,partial)
Build235 x86_64已生成Developer ID严格签名App/DMG,独立只读挂载、12,912文件/30符号链接/330原生组件及安装树核同;107个Python模块与CLI冻结code object逐项对应当前源码,176份软件源码SHA未漂移。已在无活动Session、无旧客户端或采集工具进程时同址覆盖/Applications/Perfowl.app,正常路径保留;Build234旧包及独立解包核同的回滚保留在私有批次,不另装并行版本。安装后的core在源码目录外、最小PATH下probe ready,无手机动作。
- 当前内部包:
MacApp/dist/Perfowl-235-macos-x86_64-internal.dmg,143,908,281 bytes。 - SHA-256:
c826186684879ac97b9474dc900aa6117939c92cf456a32c09dccdee73e929bf。 codesign --verify --deep --strict和DMG校验通过;公证未完成,Gatekeeper退出3、stapler退出65,不能当作可对外正式交付。系统安全配置未改,GPL法务门仍开放。- dist只保留235包及SHA;已核可替代的本批私有候选App注销并删除,原始/失败/回滚证据保留。空间检查始终高于10GiB底线,不清理其他项目。
Owner复测建议:新开测试先核默认包含Startup与ScreenShot;取消截图/某组后,新Session确认无对应新数值或截图请求;当前Session改选仅影响下一场;不选Startup保留FTime时查看AT路径及来源账本,不能把未开放的新独立CP默认策略当已实现可用。静态无新帧保持缺值,动态场景与实际成本需另有新鲜E4;本批不自动操作手机。
整体状态:partial,正式55/66、余11项暂停。下一由Lead独立审查方案偏差、能力/power账本、附带算术裁剪、完整资源与默认CP准入,再结合Owner新E4决定下一动作;Implementation不宣布阶段PASS。网站/双远程及通知以本批实际交付收据承接,不把软件包安装等同于这些门已关闭。
14.8 网站门与交付联动 · 2026-10-29
本批固定Node24.19.0完整client/server/render构建退出0,73.781秒;66项Canonical/十要素/侧栏/总览治理门通过,本批新增链接与不可变新归档已纳入。生产dry-run退出2,feature工作树、WIP和GitHub main非当前来源触发既有门;build/upload次数均0,未上传,不把本地构建冒充线上发布,不切main、不合并或绕过guard。生产网站状态partial。
本批包安装、开发记录/知识页/总览/首页/时间线联动及新HTML归档已记录;GitLab只尝试一次、GitHub同提交推送和最终通知的实际结果保留在本批交付收据。无新E4、无新增指标验收;当前公开内容仍维持55/66与全部未关闭门。