FTI-002 · Memory Contract v2 内存指标修复开发方案

日期:2026-09-16 · 类型:approved plan · 阶段:P2 · 证据:E1

对应 internal/field-test-issues.md 的 FTI-002。本快照冻结已批准方案;后续实现结果和 E4 证据不得反向改写本页,而应新增结果/验证记录。

目标

统一知识库、Metric Registry、Collector、Session、历史兼容、Export/Report 与 Workbench 的内存语义,冻结 memory-contract.v2。

产品指标metricIDScope来源 / 公式状态
Memory / Physical Footprintios.process.memory.physical_footprintprocessphysFootprintcanonical
Real Memoryios.process.memory.realprocessmemResidentSizePerfDog 等价性待 E4
Virtual Memoryios.process.memory.virtualprocessmemVirtualSizecanonical
Available Memoryios.device.memory.availabledeviceXNU memorystatus candidatecandidate
Free Memoryios.device.memory.freedevicevmFreeCount × VMPageSizeBytescanonical

新 Session 不再把 ios.process.memory.xcode_gauge 和 ios.process.memory.resident 当作独立产品指标;它们仅保留历史兼容/术语语义。

Canonical 文档门禁

产品代码修改前以 site/knowledge/metrics/memory-metrics.md 为唯一知识页。该页必须明确:Xcode/Resident 别名去重、Virtual 地址空间语义、Free 与 Available 分离、process/device scope、bytes→MiB/GiB、missing 不补 0、历史 Available→Free 只读迁移,以及单张 Memory Usage 卡片的五值/多曲线交互。

历史兼容:旧 Available 必须迁移为 Free

legacy availableMemoryBytes
        ↓
freeMemoryBytes
quality = legacy-free-mislabeled

new availableMemoryBytes
        ↓
missing
quality = missing-legacy-contract

新 Session 写入 memoryContractVersion = memory-contract.v2。历史文件保持只读,不批量改写。

Track A / Track B

Track A:Memory、Real、Virtual、Free、alias 去重、contract version、历史迁移、Session、Export/Report、Memory Usage UI,可直接实施。

Track B:Available 独立执行字段探针、XNU candidate、内存压力实验与 PerfDog 同窗 E4。Track B 未关闭时 Available 只能是 candidate/missing,不能阻塞 Track A,也不能恢复旧 Free-as-Available 行为。

Memory Contract v2 公式

MemoryBytes  = Processes[targetPID].physFootprint
RealBytes    = Processes[targetPID].memResidentSize
VirtualBytes = Processes[targetPID].memVirtualSize
FreeBytes    = vmFreeCount × VMPageSizeBytes

AvailablePagesCandidate =
    vmFreeCount
  + vmExtPageCount
  + vmPurgeableCount
  + secludedOverTarget   # 仅确认可得且语义可靠时加入

AvailableBytes = AvailablePagesCandidate × VMPageSizeBytes

若普通 sysmontap 无法可靠取得 secluded,允许 free + ext + purgeable 的 candidate-xnu-no-secluded 版本;任一必要字段缺失则 Available missing,不以 Free 顶替。

实现范围

UI 与单位

Memory       Real        Virtual
182.1 MiB    233.0 MiB   394.6 GiB
●            ○           ○

Available               Free
—                       43.5 MiB
○                       ○

              [同一张趋势图]

底层始终保存 bytes;UI 小于 1 GiB 默认 MiB,大于等于 1 GiB 默认 GiB,至少 1 位小数。Virtual 与其它 series 量级差异不能通过篡改原值解决。

E2 与 E4

E2 必须覆盖五项公式、字段缺失/负数/NaN、alias 去重、旧 wire 解码、历史 available→free 迁移、Session finalize/reload、Export 与 UI toggle。

E4 至少覆盖静止、滚动、高内存页面、前后台、多 App/内存压力和 5–10 分钟长会话;同窗记录 Perfowl 五项 + raw 字段,并与 PerfDog Memory/Real/Virtual/Available 比较绝对值、趋势、峰谷和压力响应。

性能门禁

不新增 source,新增内存计算保持 O(1) / sample。禁止额外设备 RPC、高频 polling、第二份完整 Session 缓存或 UI 每次刷新重读全量 Session。长会话必须比较 Collector/Mac CPU、RSS、bytes/min、UI render latency、first-data latency、Stop/finalize latency。

开发顺序

Phase 0  Canonical 知识页 / 公式入档
Phase 1  Available 字段 Probe
Phase 2  Registry / MetricEngine
Phase 3  Wire / PerformanceSample / Legacy Resolver
Phase 4  Session schema / historical migration
Phase 5  Export / Report
Phase 6  Memory Usage 单卡片 UI
Phase 7  E2 全链测试
Phase 8  PerfDog E4 Available 校准
Phase 9  长会话性能 benchmark
Phase 10 按 E4 更新知识页 Evidence / Quality

FTI-004 暂停期间的保护

FTI-004 当前暂停但工作区已有相关修改。FTI-002 必须基于最新内容逐 hunk 修改,不使用会丢弃未提交变更的 reset/checkout,不整文件覆盖 Workbench/CapturePlan 文件;无法安全隔离时使用独立 worktree。

关闭条件

  1. 知识页、Registry、Collector、Session、UI、Export 统一为五项 Memory Contract v2。
  2. Xcode / Resident 不再作为新 Session 独立产品指标。
  3. Free 与 Available 公式/scope/quality/version 完全分离。
  4. 历史 Available 只读迁移为 Free;历史原文件不改写。
  5. 新 Session 写入 memory-contract.v2,五项跨实时/Review/Export/Report 一致。
  6. Memory Usage 单卡片五值;默认 Memory 曲线;其它四项独立 toggle、多选。
  7. Missing 不补 0,Available 不以 Free 冒充。
  8. Available 通过字段探针和 PerfDog E4 后才允许提升证据状态。
  9. E2、E4、历史兼容和长会话性能门禁全部关闭。

追溯