路 A · Mac 参考指纹:把 XNU-7195 原始内核汇编(WKdmCompress_16k.s、lz4_encode_arm64.s)直接链接成参考程序,对 7 种确定性数据模式各 64 样本计算两算法输出指纹——与设备字节级同源(patterns.h 共享)。
路 B · 设备行为探针(cspray v9):喷洒 96MB 特定模式匿名内存 → posix_spawn 双 ballast(2×2.2GB 自适应)把 free 压入回收区间 → 全页被压缩后取快照 A → 全页重读(解压 + fnv1a 校验)取快照 B → PHYS = cusedA − cusedB 即我方页面物理压缩字节。九轮协议迭代解决 COW 记账、窗口污染、file cache 吸收等问题。
路 C · 设备端基准(本篇新增):把同一套内核汇编链接为 iOS 可执行(设备端 ldid 签名),在 A14 上实测 10 种数据形态 × 双 codec 的编解码延迟与输出大小。
| 数据形态 | WKdm 输出 | LZ4 输出 | 纯WKdm预测 | HYB预测* | 设备实测 perpage | 判定 |
|---|---|---|---|---|---|---|
| zeros 全零页 | 4B (MZV) | 193B | SV 4B | SV 4B | — | (环境性未采样) |
| dict16 指针页 | 7594.5B | 11488.1B | 7594 | 7594 (<阈值) | 8448.5 / 8451.4 / 8467.6 | ✓ WKdm(3 次复现,+1KB 槽对齐+~850B 段开销) |
| random 随机 | FAIL | FAIL | raw | raw | 1.0067(校准轮) | raw ✓ |
| ramp251 周期斜坡 | FAIL | 441B | raw | 441 | 16305.6 / 16234.8 | raw copy —— LZ4 兜底未发生! |
| singleval 单值页 | 4B (MZV) | 201B | SV | SV | 45.5 / 69.5 | ✓ SV 单值路径 |
| dict256 256词字典 | FAIL | 13836.4B | raw | 13836 | 16264.7 | raw copy —— 同上 |
| r3rep1 阈值区构造 | 14289.5B | 15390.5B | 14289 | 15390 (≥12288 必换LZ4) | 14289.0 | 精确 = WKdm 原样存储,未被 LZ4 替换! |
* HYB 规则(vm_compressor_algorithms.c):WKdm 先行;失败或输出 ≥ 12288B(16KB 页的 75%)→ 改试 LZ4 且无条件存储;LZ4 也失败 → 16KB 原样副本。
sysctl -w vm.lz4_threshold=1(HYB 下每页成功压缩都会 ≥1,应全部转投 LZ4 存储):
| 条件 | HYB 预测 P1 perpage | 实测 | 结论 |
|---|---|---|---|
| threshold = 12288(默认) | 8448(WKdm 7594 < 阈值,存 WKdm) | 8448.5 | ✓ |
| threshold = 1 | ~12400(全部转 LZ4@11488+开销) | 8451.4(Δ<0.3%) | HYB 分支从未执行 |
vm_compressor_current_codec ≠ CMODE_HYB,本机实际以纯 WKdm 模式运行(CMODE_WK 或 legacy 默认路径,二者行为不可区分)。boot-args 为空已排除启动参数覆盖;开源源码 arm64 默认是 HYB —— 差异在 Apple 内部构建配置。同一套 XNU 内核汇编(与真机内核同源),iPhone 12 Pro Max 单线程用户态,64 页 × 7 遍取中位,全部往返校验通过。时间单位 µs/16KB页。
| 数据形态 | WKdm 编码 | WKdm 解码 | WKdm 输出 | LZ4 编码 | LZ4 解码 | LZ4 输出 | 胜负 |
|---|---|---|---|---|---|---|---|
| zeros 全零 | 3.58 | 0.67* | 4B MZV | 2.60 | 45.08 | 193B | WKdm 48× 小 |
| singleval 单值 | 8.21 | 0.67* | 4B MZV | 2.61 | 31.21 | 201B | WKdm 50× 小 |
| dict16 指针页 | 31.29 | 23.13 | 7594.5B | 56.40 | 25.67 | 11488.1B | WKdm 快1.8× 且小1.5× |
| heap50 半满堆 | 31.16 | 26.87 | 8628.6B | 59.61 | 18.41 | 10555.1B | WKdm 快1.9× 且小1.2× |
| r3rep1 阈值区 | 13.64 | 9.20 | 14289.5B | 40.62 | 5.47 | 15390.5B | 各擅一场 |
| ramp251 周期斜坡 | 1.18 | — | FAIL | 3.16 | 1.02 | 441.0B | LZ4 独赢 37× |
| dict256 256词字典 | 13.17 | — | FAIL | 69.06 | 13.32 | 13836.4B | LZ4 独赢 |
| text ASCII词汤 | 7.34 | — | FAIL | 67.08 | 14.73 | 10434.3B | LZ4 独赢 |
| ptr300 指针池 | 8.98 | — | FAIL | 69.67 | 12.53 | 14080.6B | LZ4 独赢 |
| random 纯随机 | 1.17 | — | FAIL | 35.13 | — | FAIL | raw copy(memcpy 0.79µs) |
* MZV 广播解码(SV 路径,4B 槽位广播 16KB),非真实解码。FAIL = 超出 16380B 预算放弃。memcpy 16KB = 0.79µs(20.7 GB/s)。
用第 3 节实测数据按内存构成加权,模拟三种真实负载下「纯 WKdm / 纯 LZ4 / HYB 混合」的存储成本与编解码开销:
| 负载构成 | 策略 | 存储 B/页 | 压缩率 | 编码 µs/页 | 解码 µs/页 | 内存节省** |
|---|---|---|---|---|---|---|
| A · App 日常堆 28%零+25%半满堆+15%指针+… | 纯 WKdm | 8150 | 0.497 | 16.0 | 10.9 | 基准 |
| 纯 LZ4 | 7903 | 0.482 | 40.2 | 24.7 | 3.0% | |
| HYB 混合 | 6781 | 0.414 | 32.1 | 13.3 | 16.8% | |
| B · 媒体/图形 25%周期瓦片+20%纹理+15%色表+… | 纯 WKdm | 14254 | 0.870 | 6.7 | 2.5 | 基准 |
| 纯 LZ4 | 9231 | 0.563 | 37.1 | 10.8 | 35.2% | |
| HYB 混合 | 9115 | 0.556 | 40.6 | 6.8 | 36.0% | |
| C · 计算/数据 40%随机+25%周期+15%半满堆+… | 纯 WKdm | 13523 | 0.825 | 9.1 | 6.9 | 基准 |
| 纯 LZ4 | 9927 | 0.606 | 32.9 | 8.9 | 26.6% | |
| HYB 混合 | 9240 | 0.564 | 27.3 | 7.7 | 31.7% |
** 相对同负载下最差策略的存储字节。HYB 按内核真实规则模拟(WKdm 先行,失败或 ≥12288B 转 LZ4 无条件存储,MZV→SV,双失败→raw)。
WKdm 利用词级值统计:32 位词打标签(零词 2bit / 字典命中 4bit / 新词 32bit),16 槽滚动字典。真实内存页的冗余恰好在词级——零填充、重复指针、小整数簇。它是 90 年代 IBM 专为内核换页压缩设计的:固定成本、无跨页状态、超预算立即放弃、最坏情况可证明——这正是持锁内核回收路径最看重的性质。
LZ4 利用字节级位置回溯(LZ77 窗口):不管值统计,只要结构重复就能抓到。ramp251(周期 251B 的计数器/瓦片型数据)压到 0.027,dict256(色表型)压到 0.844——这两类 WKdm 全部放弃。
两者失败集合几乎不相交:dict16 词冗余高但顺序乱(LZ4 找不到长匹配 11488B vs WKdm 7594B),ramp251 词冗余低但结构强重复(WKdm FAIL vs LZ4 441B)。这正是 HYB 设计的逻辑:WKdm 先筛(便宜且覆盖主形态),硬页换机制再试(LZ4 兜底),都失败才付 16KB 存储成本。此外内核还有负载级自适应预选器(compressor_preselect,LZ4 连胜→跳过 WKdm / 连败→永久跳过 LZ4),iOS 14 默认休眠,iOS 18 起开放 sysctl 调节。
| 版本 | arch | 变化 |
|---|---|---|
| iOS 12 (4903) / iOS 13 (6153) | arm64 | 相同:HYB 默认,lz4_threshold=2048 |
| iOS 14 (7195) | arm64 | +popcount 快速检测;16K 页时 threshold 补丁为 12288;本机行为=纯 WKdm(构建配置差异) |
| iOS 15 (8792) | arm64 | +__ARM_16K_PG__ 条件编译;metacompressor 与 7195 逐字相同 |
| iOS 18 (11215) | arm64 | tuneables 改为 sysctl 可变(运行时可调 codec/threshold) |
① 内核 panic 复现:极限内存压力(free<500 页)触发 "226165 is locked down (0x6800000000000000), cannot remove" 内核崩溃(panic-full-2026-09-11-114535.ips 已归档)。后续实验必须设 free 地板(≥1400 页)。
② 压缩器惰性:file cache 未耗尽前(可回收池 1–3.5GB 随机波动)压缩器完全静止——dCin 逐秒冻结是最可靠的「没在工作」判据。矩阵实验必须带重试。
③ task_for_pid 分级:pid>0(含 launchd)✓;pid=0(内核端口)✗ 0x5——四项 entitlement 齐全仍被拒,内核内存直读不可行,本报告靠行为实验替代。
④ 设备端签名是唯一解:Mac 侧 ldid 签名一律 SIGKILL(137);上传未签名二进制后设备端 /usr/bin/ldid -S/tmp/ents_full.plist(get-task-allow + task_for_pid-allow + no-container + system-task-ports)才被认可。
⑤ cused 记账只含对齐 payload:per-slot 按 1KB 对齐(WKdm 7594→8192/9216),段级还有 ~850B/页固定开销——把设备 perpage 与参考输出直接相减即可校准。
| 文件 | 说明 |
|---|---|
src/cspray.c | 设备行为探针 v9(快照协议:ballast 协调 + A/B 快照 + fnv1a 校验) |
src/bench_codec.c | 设备端双压缩器基准(本页 §3 数据源,链接 XNU 原始汇编) |
src/refcomp.c + patterns.h | Mac 参考指纹(§2 路A),两端字节级同源 |
bench/bench_results.json | §3/§4 全部原始数据(含混合负载构成定义) |
device/*.txt | 13 个设备运行日志(矩阵两轮 + 协议验证五轮 + 阈值终审) |
panic/*.ips | 内核 panic 日志 |
全部数据归档于实验机 raw-data/ios-compressor-verify/;XNU 源码锚点见 xnu-source-analysis skill(第十批)。