FTI-003 / FTI-004 · CoreProfile Raw Retention 与存储策略实现
日期:2026-09-16 · 类型:implemented · 阶段:P4 · 证据:E2
对应 internal/field-test-issues.md 的 FTI-003 / FTI-004。默认采用 derivedOnly(产品默认),长会话磁盘占用从 ~10 GiB 降低至数百 MiB,研发调试显式选择 full 保留完整外部 blob 契约。
硬边界 (Rule 0)
- 不改 CoreProfile 是否持续采、Startup/FrameTime 合并逻辑、filters、kperf owner、Startup completion、Frame decoder;
- 不改变
capturePlanHash/CollectorReadiness/prewarmGeneration的输入集合——storagePolicy/retention永远不参与这些计算; - 降级逻辑(quota/low-disk/writer-error)只能在
RawSessionRecorder内部吞掉异常并标记truncated,绝不允许异常传播到SessionWriter.append()。
实现架构
UI Settings: @AppStorage(PerfowlSettingsKey.retainCoreProfileRaw)
↓
PerformanceSessionPlan (schemaVersion: 3, storagePolicy)
↓
CollectorSupervisor (wire: "coreProfileRawRetention": "derivedOnly" | "full")
↓
RawSessionRecorder:
- open(): 惰性创建 core-profile-chunks.bin(derivedOnly 永不创建)
- append():
derivedOnly -> 不落盘 blob, raw-events 记 chunkRetention: not-retained, 内存保留 raw chunk 供实时解码
full -> 维持 external-blob-v1 契约, 写异常内部消化并标记 truncated
- manifest.json: 诚实区分 observed / persisted 计数,derivedOnly 不输出 blob 文件与散列
验证结果
- Sidecar Python 自动化测试:407/407 通过;
- Swift Core/App 自动化测试:149/149 通过;
- Unified CoreProfile 单 tap 连续采集测试:9/9 通过。