全指标采集、实时窗口与快速收尾修复方案

1. 决策与批准边界

**方案完成,实施待用户批准。**本批只交付设计与验收合同,不变更产品代码、冻结依赖或指标算法。基线为 a9cab40 / Build 38 / Foundation 2.7 Beta。本文 E1 表示设计与代码审查;此前留存会话属于真实运行证据,但不代表修复后 E4 通过。八项问题全部进入范围,不把“入口可选”当作指标已支持。

保持唯一连接 Provider / DTX owner;不引入第二套连接内核。采用“全源准备、采集与展示解耦、单次解码增量派生、有界实时视图、增量报告封存”。放弃只增加超时、扩大缓存及停止后全量重放作为默认路径。代价是需要新的持久化检查点和恢复机制;收益是实时开销不随会话历史无限增长。

2. 已确认的用户规则

3. 八项问题与证据边界

最近两份匿名留存会话暂称 A/B,后续验证用本地私有映射确认用户测试对应关系。A 约 82.61 秒、80 sample、Raw 18.54 MB;B 约 19.02 秒、15 sample、Raw 267.49 MB。时长并非 Raw 大小的唯一决定因素。

问题 当前事实 / 假设 修复与关闭条件
启动全部 missing 两份 decodedRecordCount=0、span=0;B 有 liveQueueDropCount=19。源格式/覆盖存在缺口,尚未定位唯一根因 审计原始头、分片、时钟、丢失、生命周期归属;源解码通过后才进入阶段映射。可控因果测试后再验证商店应用;无证据不补猜测阶段
Mac 滚动卡顿 图表重复调用 playbackPoints;该属性每次排序整个 points。可见窗口虽为 60 秒,计算仍依赖历史 N。主线程占比尚未实测 固定窗口缓存、预先排序、后台分段、可见区域渲染;滚动性能及 RSS 随时长稳定
Frame Time missing 两份 acceptedRecordCount=0;A ignored=5,B unknown=27/ignored=17 恢复有效逐帧源、时钟及连续性;逐帧输出与独立回放一致,再校准归属与单位
Memory / XcodeMemory 相同 两者当前均读 physFootprint;后者是 candidate-alias 同源明示,拒绝伪造独立口径;与工具同窗对照前保持 candidate-alias
AvailableMemory 61.1 当前 vmFreeCount×VMPageSizeBytes,只代表空闲页口径;尚未逐点复核该值 核对原始页数、页大小来源、单位和取整;不能拿整机空闲量与进程占用作大小正确性判据。完整可回收容量另立证据门禁
GPU 三项相同 留存 Raw 有 45/44/45、3/2/3,也有完全相同;不是“同值即错误” 三个原始字段→metricID→Wire→图表逐层追踪;禁止互相 fallback;空闲/动画/负载同窗核查
Thermal Status missing 稳定当前等级源仍开放 查明受支持系统回包与枚举;未获得源前展示 source-missing,不用温度或通知名称推算
GPU Counter 等待 旧批已知 schema/heartbeat 不代表 data row;当前两份无 gpu.counter.raw,尚需核对选择和 Adapter 生命周期 区分未启动、探测失败、schema-ready、首行超时、有效行与断流;源及单位具证据才关闭
停止随负载变慢 delivery.py 串行校验、metrics、frames、report、startup、launch_trace、mapping、calibration;多次读/解码风险 增量派生、封存检查点;停止后不扫描全量 Raw;完整报告与独立审计分开标识

以上表格将内存两项拆开说明,但用户八类问题范围不变。留存 finalizer 子阶段耗时合计 A 约 0.818 秒、B 约 3.585 秒,仅包含已记录阶段,绝非点击停止到报告的端到端耗时。需新加完整边界测量。

4. 状态机与并发所有权

Disconnected → DevicePreparing → DeviceReady → AppPreparing → Prepared → Starting → Recording → CaptureStopped → Sealing → ReportReady。

每个源独立记录 unprobed/preparing/prepared/activating/streaming/missing/failed/timed-out、原因、最近有效时间和证据级别。全局 Prepared 表示必要源可运行,展示可运行源数量与失败项,不把全部指标宣称 ready。

应用、设备、指标配置绑定 generation。切换应用立即取消旧准备,迟到回包不得推进新 generation;断线、锁屏、失效 tunnel 触发重新验证。开始期间禁止重复提交;停止幂等;starting 期间也能取消,取消后禁止迟到 launch。停止超时后隔离旧 owner,未确认释放前不复用其 socket。

DTX 单 reader 只分发,不做大 JSON、base64、重解码和磁盘 fsync。每个流保持源内顺序。控制通道优先、普通源与重型源分队列;并发探测建议上限 2,协议要求串行的服务仍串行。writer 单所有者;重型解码优先采用单个受控 worker,线程受 GIL 限制时用对照数据决定是否迁移独立进程,避免盲目增加线程。截图单并发,不允许定时任务堆叠。

启动窗口启用后必须先接收有效就绪信号再 launch;激活时间计入 click-to-launch。若临时激活超过目标,明确展示 activating,禁止为了“秒开”先启动再丢 prelaunch 证据。准备 TTL、激活耗时与跨源冲突进入基线测试。

5. 轻量数据管线与一致性

唯一设备连接 / 单 DTX reader
  → 小型有序 Envelope + 有界分发
  → Raw 单 writer(持续哈希、分段索引、检查点)
  → 一次解码 → 普通指标 / Frame / Startup 增量引擎
  → 完整派生流与报告聚合持久化
  → 实时窗口快照 → 可见图表

Raw 记录是事实源,派生事件携带 raw sequence、算法版本、源质量与 generation。跨源只按可证明时间关系合并。存储 schema 若升级必须加版本、新旧读取兼容和 fixtures,旧会话不回写。

建议重型内存队列维持当前 64 MiB 上限作为起点,32 MiB 预热预算不盲目扩大。按观测 p95 吞吐 R 配置服务能力至少 1.5R,2R 短突发验证缓冲;磁盘落后时显式积压/丢失事件。磁盘 spool 亦设可配置容量和剩余空间阈值,满盘触发 partial 并停止受影响源,不无限缓存。

主机流式哈希只能证明主机所收记录的完整性,不证明设备无丢失。写盘与派生分别维护 durable sequence;checkpoint 仅在相应 fsync 成功后推进。停止时 seal_sequence 必须被全部必要派生引擎消费。崩溃恢复从最后 durable checkpoint 回放尾段,重复 sequence 幂等;保留离线全量审计命令,但不强制放进每次点击停止关键路径。

6. 固定窗口图表

设总事件 N、窗口秒数 W=60、采样率 r、可见曲线数 V、绘图宽度 P。

7. 随开随停与 2 秒报告合同

下列是待批准的目标预算,不是已测成绩。使用 host monotonic 时间,设备启动阶段继续使用其证据时钟,不混用。

边界 目标 计时与适用条件
点击→UI 状态反馈 p95≤100ms、max≤200ms Mac 本地;包括 starting 时取消
已准备→唯一 launch 请求 p95≤500ms 含启动源实际激活;普通/启动两种模式分测,设备请求完成另记
点击→关闭采样边界 p95≤100ms、max≤200ms 关闭样本接纳,不等于设备已释放;晚到 drain 事件隔离为收尾数据
设备源关闭与 lease 释放 p95≤1s、max≤2s 正常设备;异常分支限时隔离,不能将超时称成功释放
普通 Raw 接收→Wire p95≤250ms 首点 warmup 不补 0;慢频率源不套用 250ms 首次出值目标
点击停止→完整报告 ready 每个验收样本≤2s 从点击开始计时,含 drain、持久化与索引封存;不是只测绘制摘要

报告 2 秒要求在明确的产品支持规模内验证,初始矩阵 1/10/30/60 分钟,Raw 20 MB/300 MB/1 GB、全部常规源与两项可选源组合。更大规模不能自动推定通过。报告 ready 必须包括截至 seal 的完整常规曲线、统计及每个选中源的终态质量。深度源本身缺失可显示 missing 原因,正在积压计算不得伪装完整报告。若未满足尾段预算,显示 finalizing/积压与原因,该样本判 2 秒门禁失败。

为避免把重任务转移到采集中导致新卡顿:每秒观察 queue lag、decode throughput、writer throughput、主线程帧耗时和设备扰动;持续服务率低于输入率时门禁失败。离线 schema 研究、未知码 census、全量二次审计不属于用户报告必需产物,可显式后台独立执行,状态单列。

8. 指标口径处理与资料门禁

本方案不修改现有数学公式。实施前每个口径变更必须先更新对应 Canonical 页十要素、历史记录和测试。

若在固定版本实验中仍无源,交付研究结果和所需资料,不承诺通过工程重构创造该能力。所需资料:对应系统版本的匿名原始协议回包、受控负载/阶段标记及同窗结果;付费账号或凭据不写入文档。当前无需再次换连接库。

9. 分批实施与依赖

批次 工作 产物与通过门禁
R0 基线与可观测性 两份留存重放;端到端时标、主线程 profile、队列/CPU/RSS/I/O 基线;确认版本及会话对应 匿名机器证据和基线;有时间戳不等于 E4 修复
R1 全源准备与策略解耦 采集配置/展示配置分开;准备状态机、generation、幂等开始停止、选项冻结、源独立失败 常规曲线全隐藏仍采全量;两项可选准备但未启用时无持续 Raw;设备切换和取消测试
R2 实时窗口与主线程瘦身 固定窗口缓存、可见性、后台分段、截图缩略图;移除全历史排序 60 分钟采集滚动性能不恶化、完整落盘点数不减少;与基线比较
R3 单次增量派生与报告封存 writer/checkpoint、共享解码、分段报告、恢复、尾段预算 离线独立 replay 与在线派生一致;崩溃/满盘/断连;每轮完整报告≤2s
R4 启动/Frame 源闭环 解码格式、分片头、时钟、loss、生命周期/帧语义逐层验证 可控正负例和因果测试,再目标应用 E4;没有源证据保持 partial
R5 内存/GPU/Thermal/Counter 逐点映射、同源解释、字段审计、状态反馈、数据行补齐 原始到显示证据链;Thermal/Counter 未取得真实值则该项保持开放
R6 整体验收与发布 全源+可选组合、长短会话、数值回放、资源开销与公证产物 站点归档、签名公证/独立安装、窄范围提交双推送、Webhook

依赖 R0→R1→R2→R3;R4/R5 复用 R0 证据并在 R3 后做完整回归,R6 汇总。用户批准本方案后逐批开发,每批有独立结果与开放门禁;未经批准不启动实施。资源与耗时目标以实验收敛,不用未验证工期承诺替代技术门禁。

10. 测试与效率预算

以下预算待基线确认后由用户批准调整,禁止测试后降低标准以宣称通过:

11. 交付与回滚

仅方案阶段:Markdown、HTML 快照、时间线登记、构建与链接检查、窄范围提交、双远程推送尝试及 Webhook。本文前述均为设计,不宣称开发完成或数值已修复。

实施后:增量写入/报告 schema 和窗口实现均保留受控 feature flag;回滚不破坏新旧 Session 读取,切换只在会话边界生效。性能退化、sequence 丢失、报告 hash 不一致触发暂停推广并保留证据。

正式产品交付需 Developer ID、Notary accepted、staple、Gatekeeper、独立解包/安装与 SHA-256;证书/公证或法务未就绪保持 partial,不把内部包冒充正式包。每批本地窄提交并对两个远程分别记录结果,保留既有无关工作区变更。

交付最终汇报前发送企业微信 Webhook,地址从环境变量或 Keychain 读取且不输出;仅 HTTP 2xx 且 errcode=0 视为成功。失败交付标 partial 并说明重试方式。

12. 当前进度与下一阶段

本轮完成 E1 修复方案;已知八类问题仍开放,旧 E2 测试数不等于新体验通过。下一阶段等待明确批准后执行 R0 基线及 R1 策略解耦,再按 R2~R6 收口。64 项 Registry 是合同定义数量,不是 64 项在所有系统均具备 E4 数值能力。

代码溯源:MacApp/Sources/PerfowlCore/SessionTimeline.swift 的 playbackPoints;MacApp/Sources/PerfowlApp/PerfowlWorkbenchView.swift 的 WorkbenchMetricChart/segments;MacApp/Sidecar/perfowl_collector_core/{realtime,recording,delivery,metric_engine}.py。历史证据:上一轮修复、最终 HEAD 回归。