Skip to content

CoreProfile Raw Retention 与存储策略实现 (derivedOnly vs full) ​

关联背景与问题 ​

  • 关联问题:FTI-003 / FTI-004 · CoreProfile Raw 整场持续落盘导致长会话磁盘膨胀
  • 现象:启用 FrameTime 持续采集后,CoreProfile binary chunk 持续原样追加到 core-profile-chunks.bin,5 分钟长测即产生约 10 GiB 的 Raw 文件与持续数十 MiB/s 的磁盘 I/O。
  • 目标:默认采用 derivedOnly(产品默认),不生成也不落盘 core-profile-chunks.bin,内存保留原始 chunk 供实时解码器解析,将长会话磁盘占用从 ~10 GiB 降至数百 MiB;研发调试显式选择 full 保留外部 blob 契约。

硬边界遵守情况 (Rule 0) ​

  1. 不变动采集核心:CoreProfile 持续采集、Startup/FrameTime 联合 filter、kperf owner 独占、Startup completion、Frame decoder 逻辑均未做任何变动;
  2. 读就绪与哈希隔离:capturePlanHash、CollectorReadiness、prewarmGeneration 的输入严格排除 storagePolicy / retention,切换 retention 绝不触发 Collector 重启或重武装;
  3. 异常消化:任何 quota/low-disk/writer-error 均在 RawSessionRecorder 内部降级为 truncated,严禁异常外溢至 SessionWriter.append()。

实际修改范围与关键文件 ​

组件文件修改说明
Sidecar Coreperfowl_collector_core/storage_policy.py (新增)定义 CORE_PROFILE_RETENTION_DERIVED_ONLY, CORE_PROFILE_RETENTION_FULL, SessionStoragePolicy, RawRetentionLimits 及真值表解析函数 resolve_core_profile_raw_retention
Sidecar Coreperfowl_collector_core/__init__.py导出上述符号与常量
Sidecar Coreperfowl_collector_core/recording.pyRawSessionRecorder 惰性创建 blob 文件;derivedOnly 不写 blob 并将 payload chunk 标记为 chunkRetention: not-retained;manifest 区分 observed 与 persisted 计数;降级捕获写入异常标记 truncated;validate_recorded_session 兼容 derivedOnly 与历史 full
Sidecar Coreperfowl_collector_core/delivery.pyfinalize_candidate_session 对 derivedOnly 抛出 ReplayValidationError("core-profile-raw-replay-unavailable")
Sidecar Coreperfowl_collector_core/recovery.pyrecover_checkpoint 与 _append_contiguous_tail 支持无 external blob 的会话恢复
Sidecar Coreperfowl_collector_core/realtime.pystream_candidate_session 顶层统一绑定 retention_policy,传递至 RawSessionRecorder
Sidecar CLIperfowl_collector_core_cli.pystart 命令 wire 协议解析 coreProfileRawRetention;stream 命令行支持 --core-profile-raw-retention
Sidecar Teststests/test_storage_policy.py (新增)覆盖真值表、derivedOnly 无 blob、full blob 契约、解码一致性、离线回放防御、历史数据兼容、写异常降级、实时封印不走离线回放 8 个专项测试
Swift CoreMacApp/Sources/PerfowlCore/SessionStoragePolicy.swift (新增)Swift 侧 CoreProfileRawRetention 枚举、SessionStoragePolicy 结构体、PerfowlSettingsKey 定义
Swift CoreMacApp/Sources/PerfowlCore/PerformanceModels.swiftPerformanceSessionPlan 升级到 schemaVersion 3,向后兼容解码 schema 1/2 为 historicalFull;增加 Rule 0 硬边界注释
Swift CoreMacApp/Sources/PerfowlCore/CollectorSupervisor.swiftstartPreparedSession 与 CollectorLaunchConfiguration 连通 wire 字段 coreProfileRawRetention
Swift CoreMacApp/Sources/PerfowlCore/PerformanceSessionController.swiftstart 接收 storagePolicy,设置到 Session plan 并传递至 supervisor
Swift AppMacApp/Sources/PerfowlApp/PerfowlWorkbenchView.swift设置面板增加 @AppStorage(PerfowlSettingsKey.retainCoreProfileRaw) 切换项,toggleCapture() 按设置注入策略
Swift TestsMacApp/Tests/PerfowlCoreTests/SessionStoragePolicyTests.swift (新增)覆盖 Rule 0 哈希无关性、旧 schema 兼容为 historicalFull、schema 3 编解码与自定义策略 4 项单测

验证结论 ​

  • Sidecar Python 自动化测试:
    bash
    python3 -m unittest discover -s tests -p "test_*.py"
    # 结果:Ran 407 tests in 7.222s. OK.
  • Swift Core/App 自动化测试:
    bash
    swift test
    # 结果:Executed 149 tests, with 0 failures in 11.182s.
  • Unified CoreProfile 专项回归:
    bash
    python3 -m unittest tests/test_unified_core_profile.py
    # 结果:Ran 9 tests in 2.489s. OK.

安装包交付与校验 (Build 58) ​

  • App 产物:MacApp/dist/Perfowl.app(CFBundleVersion=58,Developer ID Application: Jiacheng Li (76J692XB5C) 签名,Hardened Runtime 开启,时间戳有效,codesign --verify --deep --strict 通过)。
  • ZIP 归档:MacApp/dist/Perfowl-internal-test-Build58-x86_64.zip(109,234,320 bytes,SHA-256: 5f4d47fe8e1fa5f3c73cdb3d8db49213ad39efcc9617f91ecd828b7eb87dc4a3,解包与签名严格校验通过)。
  • DMG 镜像:MacApp/dist/Perfowl-internal-test-Build58-x86_64.dmg(141,828,802 bytes,SHA-256: 6d82479f4a6da0ca452f36adfadca1eb9f9d3eca72dd9cfade63b274cc5b0240,Developer ID 容器签名,hdiutil verify 与挂载校验通过)。
  • 可执行文件 SHA-256:fa574c5e2294a28108bbedfa93288743b7c0fb8928d5e2a3e98001485c21f477(6,638,160 bytes)。
  • 验收报告归档:Build58 CoreProfile 存储策略与原始分块持久化分级验收
  • 匿名证据文件:docs/validation/evidence/perfowl-build58-storage-policy-e2-anonymous-2026-09-16.json

Update 2026-09-16 · E4 近 5 分钟真机磁盘验证 ​

  • Build 58 真实 Session 运行 280.123 s(4 分 40.123 秒),Session 状态 completed。
  • Session 实际逻辑文件总量 203.24 MiB;文件系统 du 占用约 205 MiB。相较修复前同类约 5 分钟 Session 10.11 GiB,磁盘占用下降约 98.0%(约 51 倍)。
  • collector-core 60.35 MiB,其中 raw-events.jsonl 57.55 MiB;screenshots 138.77 MiB,已成为本轮最大持久化项;events 1.73 MiB、raw 1.81 MiB、metrics.csv 565.29 KiB。
  • 本轮设备侧实际观察到 CoreProfile 3,753,607,010 bytes / 850 chunks,但 coreProfilePersistedByteCount=0、coreProfilePersistedChunkCount=0;core-profile-chunks.bin 未创建,coreProfileRawRetention=derivedOnly、coreProfileRawRetentionStatus=not-retained、coreProfileRawReplayCapability=unavailable,证明采集与实时解码继续工作而完整 Raw binary 不再落盘。
  • Unified CoreProfile 主路径保持 startup-and-frame,startCount=1、restartCount=0、stopCount=1,未因存储策略引入额外 CoreProfile 生命周期。
  • 本次仅完成近 5 分钟 derivedOnly 真机磁盘门禁;30 分钟长测与 full 调试模式真机对照仍待执行,因此批次继续保持 partial,不提前关闭全部 E4 门禁。

遗留项与后续门禁 ​

  • E4 真机长测对比(待真机验收):在真实 iOS 设备上运行 5 分钟与 30 分钟连续会话,验证磁盘体积由 ~10 GiB 降低至数百 MiB,确认磁盘 I/O 不再随 CoreProfile Raw 吞吐无界增长。
  • Notary 与 Stapling 门禁(开放):本机未配置 Notary 凭据,待 CI/签名机执行公证与 stapling。
  • GPL-3.0 法务评估门禁(开放):pymobiledevice3 外部依赖分发合规评估。

Perfowl · Performance Observer