02 · 用户态内存分配器竞品分析说明文档(终端设备场景)

版本:v3 · 本版评分目标 ≥90(通过线) 配套:《01-竞品分析框架与评分标准》(rubric 与协议)、《03-评分与迭代记录》(v1 80.5 → v2 85.75 → 本版修复) 数据等级标注:[S] = 本机实测 · [D] = 设计级(源码/文档,未实测) v2→v3 变更:修正 E4P 归因错误(v2 评委 A 溯源发现:E4P 文件实为 system 二进制数据——作废归档并以 mimalloc+system 双配置重测;"mimalloc 条件敏感"叙事随之撤回,真实结论为压力不敏感);E5P 补足 5 reps/配置 + 交错对照协议(排除压力窗口时间混杂:jemalloc 一批"归还"系 swap 填充期换出伪影,已识别披露);E4 增加逐 rep EMR 与 IQR 披露(system 0.573–0.815 方差极大);压力实验协议固化(hog 源码入库、free% 落盘、MANIFEST);修正表 11 统计标注口径与索引计数;E5P 因果表述与异构核归因置信度降级 v1→v2 变更:修复 E4 开销列数据错误与 ±5% 措辞(v1 评委发现);预热协议提升至 ≥1M 次并全量重测(round3);新增 E3 延迟分位、E5B 显式释放、E6 宏基准章节;新增 E5 离散度披露与归还曲线图;新增 E5P 压力耦合对照实验;机制归因表扩展;XNU 源码级证据附录

目录

  1. 执行摘要
  2. 范围与场景
  3. 竞品概览
  4. 评测方法学
  5. 实验结果
  6. 维度分析
  7. 综合对比与机制归因
  8. 场景化选型建议
  9. 风险与局限
  10. 附录

1. 执行摘要

表 1:结论总表(评级:◎ 强 / ○ 中 / △ 弱 / ✕ 不可用;数据等级 [S] 实测 / [D] 设计级)

竞品V1 性能V2 内存效率V3 安全V4 可观测V5 工程集成终端综合适配
系统 libmalloc○ [S](W2 最强)○ [S](稳态开销大、归还压力自适应)△ [D]○ [S]◎(零成本默认)◎ 基线均衡
jemalloc○ [S](W1 持平系统)△ [S](默认稳定压力下不归还)○ [D]◎ [S]○ [S]△
jemalloc-tuned*△ [S](W2 −80%)◎ [S](EMR 0.936 稳定 / 即时 RR 0.951)○ [D]◎ [S]○ [S]○
mimalloc◎ [S](小对象 4.42×)○ [S](EMR 良好、默认不归还)○ [D]○ [S]○ [S](体积最小)○
mimalloc-tuned**△ [S](W2 −96%)○ [S](即时 RR 0.90,淤积 EMR 降)○ [D]○ [S]○ [S]○
tcmalloc✕ [S] 本平台不可测✕○ [D]○ [D]✕ [S] macOS 26 崩溃✕
Scudo——◎ [D]○ [D]△ [D]△ [D]
PartitionAlloc——◎ [D]○ [D]△ [D]△ [D]
snmalloc——◎ [D]△ [D]△ [D]△ [D]
hardened_malloc——◎ [D]△ [D]△ [D]△ [D]

\* jemalloc-tuned = MALLOC_CONF=dirty_decay_ms:0,muzzy_decay_ms:0(常开激进 purge) \*\* mimalloc-tuned = 程序化 mi_option_set(mi_option_purge_delay, 0)(常开激进 purge)

核心发现:

  1. 小对象密集负载 mimalloc 吞吐 4.42×(270.2M vs 61.2M ops/s),8 线程不退化;jemalloc 与系统在纯小对象上持平(E1/E2);
  2. 系统分配器的归还是"压力自适应"的(本轮新发现,E5P 实验):释放后空闲时,无系统压力 → footprint 不降(RR=0.00–0.12,内核无需回收已标记可复用的页);人为制造压力 → 全部 rep 归还 95%+。即系统分配器在恰好需要归还的时刻(内存压力上升、jetsam 风险出现)归还 [S];
  3. 第三方默认配置在稳定压力下不归还:压力下(空闲 26–28%)jemalloc 5/5(交错)、mimalloc 10/10 reps 仍 RR=0.000(交错对照排除窗口混杂)——其缓存页是脏匿名内存,内核的常规压力响应(回收可复用页)无效 [S]。E5P 三方对比:system 0.95+ vs jemalloc 0.000 vs mimalloc 0.000;macOS 的 swap 填充极端期能换出这些页,iOS 无 swap、无此出口;
  4. 两条归还路线代价悬殊:常开激进 purge(tuned)即时归还 0.90–0.95,但 W2 吞吐 −80~−96%、淤积 EMR 反降;
  5. 显式释放 API 是零代价归还路线:mi_collect 11.5ms → RR 0.997,jemalloc purge 11.2ms → RR 0.951(无需系统压力配合),而系统 malloc_zone_pressure_relief 对 footprint 是空操作 [S]——终端正确姿势是"默认配置 + 内存压力回调调显式 API";
  6. 混合尺寸(含 ≥64KB)负载系统 libmalloc 最快(E1 W2 35.97M,第三方 0.20–0.94×);tcmalloc 在 macOS 26.4 上启动即 SIGBUS(四路径全败)。

选型建议(详见 §8):


2. 范围与场景

2.1 终端设备约束 → 评测维度映射

表 2:终端约束映射

#终端约束映射维度对应实验
C1 无 swap,RSS 即生死V2E4(EMR)
C2 系统按内存压力杀进程(jetsam/LMK)V2E5/E5B(归还速度与通道)
C3 能耗与热预算V1E1/E3(每操作开销代理)
C4 arm64 + 16KB 页V2/V5页粒度证据:jemalloc arenas.page=16384、mimalloc _mi_os_page_size()=16384 [S](round3/probe_*.json)
C5 动态注入受限(iOS 无 DYLD 通道)V5接入通道矩阵(§6.5)
C6 包体积敏感V5二进制体积实测(sizes.json)
C7 峰值内存致命V2E4/E5

无法覆盖:C3 的功耗直测(本环境无功耗测量手段,以每操作时间开销作代理,结论不声称功耗数字)。

2.2 代理平台声明

全部实验在 Apple M3(8 核 CPU(4P+4E)/ 8GB 统一内存 / arm64 / 16KB 页)macOS 26.4 (25E246) 上执行。该平台与 iPhone/iPad 终端同 ISA、同页大小、同内核家族(XNU)、同分配器后端(libmalloc),内存容量同为受限级。结论适用边界:Apple Silicon 类终端平台。向 iOS 真机外推的风险逐条见 §9.1。


3. 竞品概览

3.1 架构对比(表 3)[D]

(基于各项目公开文档、brew 配方与源码结构;本表为设计级信息,非实测)

竞品架构模型元数据布局线程本地缓存归还策略来源
libmallocnano(≤256B 槽位)+ magazine 分区 + large部分内联per-CPU(magazine)free 路径主动归还Apple 系统
jemalloc 5.3extent/slab + 232 级 size class外置(rtree/edata 独立映射)tcache(每线程)dirty/muzzy 分层 + decay 定时器Jason Evans, 2006–
mimalloc 3.5page-local free list + 分片延迟释放部分内联(页首)thread-local heap页级延迟 purge(可调)Microsoft, 2019–
tcmalloc 2.18ThreadCache → CentralFreeList → PageHeap部分内联ThreadCache(旧)/ per-CPU(新)惰性 + 显式 ReleaseGoogle
Scudo加固型通用分配器外置per-thread cachedecayLLVM/Android 默认
PartitionAllocbucket + slot span + guard region外置 + 编码thread cache按需丢弃Chromium
snmalloc元数据全外置 + 跨线程消息传递全外置local arena主动Microsoft Research
hardened_malloc加固分配器全外置 + 随机化thread-local主动GrapheneOS

3.2 实测集:版本、接入通道与活性验证 [S]

表 4:实测集配置(brew 配方编译选项见附录 §10.3)

竞品版本接入机制活性验证证据(落盘)
libmallocmacOS 26.4 系统自带默认malloc_zone_from_ptr → DefaultMallocZone(verify_*.json)
jemalloc5.3.1DYLD_INSERT_LIBRARIES 进程级注入(dylib 导出未前缀 malloc/free/mallctl,源于 brew 配方 --with-jemalloc-prefix=)mallctl("arenas.page")=16384 + malloc_stats_print Allocated≈2.7MB 与 1MB 持有+预热吻合
jemalloc-tuned5.3.1 + MALLOC_CONF同上verify .err 中 MALLOC_CONF: "dirty_decay_ms:0,muzzy_decay_ms:0" 直接证明配置生效
mimalloc3.5.0(mi_version()=30500)链接期覆盖(官方 mimalloc.o,符号级替换)mi_version() + mi_stats_print 页统计与负载吻合
mimalloc-tuned3.5.0 + 程序化 mi_option_set(purge_delay,0)同上代码路径(bench.c MI_TUNE=purge),行为可由 E5 数据区分

3.3 ⚠️ 关键发现:tcmalloc 在 macOS 26.4 上不可用 [S]

gperftools 2.18.1 的 malloc zone 覆盖机制在本平台启动即崩溃。四条接入路径全部失败:

表 5:tcmalloc 接入尝试记录(档案:experiments/data/tcmalloc-failure/)

尝试路径结果
DYLD_INSERT libtcmalloc.dylibSIGBUS(exit 138),无任何输出
DYLD_INSERT libtcmalloc_minimal.dylibSIGBUS(exit 138);崩溃点位于 libtcmalloc_minimal.4.dylib 的 __TEXT(r-x)
静态 force_load libtcmalloc_minimal.a + libc++SIGBUS(exit 138);崩溃点位于可执行文件自身 __TEXT(r-x)
静态 libtcmalloc.a(不补 libc++)链接失败(未定义 C++ 符号)

崩溃签名(bench_tc-*.ips,已归档):


EXC_BAD_ACCESS (SIGBUS) — KERN_PROTECTION_FAILURE at 0x100e5eb24
故障地址位于 bench_tc 自身 __TEXT 区段(r-x 只读)——
即 gperftools 试图写入 macOS 26 已设为只读的代码/常量结构。

归因 [D]:gperftools 在 macOS 上通过替换 malloc zone 函数指针实现接管;新版 macOS 对相关结构施加写保护,覆盖代码在初始化阶段写入只读页即触发保护故障。此结论由崩溃签名 + 机制文档推得,未逐行验证 gperftools 源码(可信度中等)。

决策:按框架 §2.1 尽力集协议,tcmalloc 降档为设计级竞品(V1/V2/V4 无本平台 S 级数据)。该发现本身是 V5 的硬数据:在 Apple 终端生态选择 tcmalloc 的可行性存疑,真机验证前应视为高风险。旧版 gperftools 尝试因 GitHub 分发通道不可达(§3.4)无法进行。

3.4 设计级集获取受限声明

snmalloc、PartitionAlloc、hardened_malloc 仅经 GitHub 分发;本环境 GitHub 直连不可达(网络策略,已测试超时),Homebrew 无对应 formula。故列入设计级集,结论置信度天花板低一档([D]),全文不表述为实测事实。


4. 评测方法学

4.1 环境 [S]

表 6:评测环境

项值
机型/SoCApple M3,8 核(4 性能 + 4 能效)
内存8GB 统一内存(受限级,贴合终端)
页大小16384 B(arm64 16K;jemalloc/mimalloc 页适配探测见 §2.1 C4 行)
OSmacOS 26.4 (25E246)
编译器Apple clang 21.0.0 (clang-2100.0.123.102)
bench 构建-O2 -Wall -std=c11 -pthread;mimalloc 变体 -DUSE_MIMALLOC + mimalloc.o
E6 构建sqlite 3.50.4 官方 amalgamation,三份同源编译(sys / +libjemalloc.a / +mimalloc.o),-O2 -DSQLITE_THREADSAFE=0
竞品来源Homebrew bottle(版本与配方编译选项见 §10.3)
harnessexperiments/bench/bench.c(统一进程、统一负载、xorshift64 确定性随机)
运行条件桌面电源接通;E1–E6 于常规空闲状态执行(系统空闲内存 27–37%,逐轮浮动);E5P/E4P 为刻意施加压力的对照实验(7GB 不可压缩 hog,空闲 ~27%,见 §5.4)——内存压力状态是显著调制变量,已在本轮识别并单独实验

4.2 指标定义(与框架 §4.4 严格一致)

表 7:指标定义

指标定义采集方法
ops/s一次"malloc+写首字节+free"循环 / 墙钟mach_absolute_time
malloc/free 延迟分位逐次计时直方图;时间基准粒度 41.67ns(24MHz),快于一个 tick 的操作读数为 0,分位数分辨率受此下限约束;快路径精确均值以 1/(E1 ops/s) 为准同上(含 ~2 次时钟读取开销,跨配置公平可比)
phys_footprinttask_info(TASK_VM_INFO),与 jetsam 判杀口径一致(源码级验证 [SRC]:xnu memorystatus_do_kill 记账、memlimit 对比基准与 band 内 kill 排序均取 get_task_phys_footprint / 其页数换算,见附录 §10.5)每 200ms 采样
EMR 有效内存比live_logical_bytes / (footprint_steady − footprint_baseline)E4
稳态开销1/EMR − 1 = (footprint_steady − baseline − live) / live(含分配器元数据与未用页,即设备真正付出的超额代价;与数据文件 overhead_pct−100 一致,由聚合脚本产出)E4
RR 归还率(peak − footprint_t) / (peak − baseline)E5/E5B,t∈{0.2,1,5,10,30}s,报告逐 rep 值与 P25–P75

碎片(外部)说明:committed 无法从第三方分配器内部读取,按框架 §4.4 以 EMR 作为含碎片+元数据的综合代理;专门的变尺寸碎片化实验为后续工作(§9.2)。

4.3 协议与可复现性


5. 实验结果

本章数据均可在 experiments/data/round3/(1M 预热合规重测)溯源;表值为中位数,离散度标注见各表附注。

5.1 E1 单线程吞吐 [S]

表 8:E1 单线程吞吐(数据:E1_*_r{1..5}.json)

配置W1 小对象 (ops/s)相对系统W2 混合 (ops/s)相对系统
system61,164,8701.00×35,973,5041.00×
jemalloc61,339,1251.00×33,696,2300.94×
jemalloc-tuned61,453,5451.00×7,091,6120.20×
mimalloc270,231,9274.42×8,108,6090.23×
mimalloc-tuned268,093,8194.38×1,516,3660.04×

离散度(IQR 相对中位数):25 个配置×线程组中 18 组在 ±4% 内,全部在 ±9% 内;最宽 jemalloc W1 t8 P25 −7.6%、mimalloc-tuned W1 t8 P75 +8.9%(均为 8 线程组)——完整逐组 IQR 见 summary.md。

观察:

  1. 小对象(≤128B):mimalloc 快 4.42×——W1 全部命中其 free-list 分片快速路径;jemalloc 与系统 libmalloc 持平(1M 预热后差距消失,v1 曾为 0.98×)[S];
  2. 混合尺寸:格局反转——系统 libmalloc 最快(35.97M),第三方均退化(0.20–0.94×);两个 tuned 变体(常开激进 purge)跌幅最深(0.20×/0.04×),机制见 §7.1;
  3. mimalloc-tuned 在 W1 上不降(268.1M vs 270.2M)——purge 代价只落在含大对象的 W2 路径 [S];mimalloc-tuned W2 比 mimalloc 默认再低 5.3×(0.04× vs 0.23×),即 purge_delay=0 的代价在大对象路径被放大。

5.2 E2 多线程扩展性 [S]

表 9:E2 多线程扩展(数据:E2_*_t{2,4,8}_r{1..5}.json;"1 线程"列引自 E1;每线程 5M ops 固定,总吞吐汇总)

配置1 线程2 线程4 线程8 线程8 线程加速比
system61.2M115.0M185.4M257.7M4.21×
jemalloc61.3M120.2M202.6M263.3M4.29×
jemalloc-tuned61.5M120.2M198.0M254.7M4.14×
mimalloc270.2M527.5M837.6M1,106.6M4.09×
mimalloc-tuned268.1M527.5M847.9M1,082.2M4.04×

观察:

  1. 无一竞品出现锁竞争塌陷:8 线程加速比 4.04–4.29×。归因说明:M3 为 4P+4E 异构核,4 个性能核满载后能效核贡献有限,4.0–4.3× 与异构算力结构一致(4×P + 4×~0.3E ≈ 4.1–4.3×)——瓶颈更可能是核的异构结构而非分配器锁(v1 版曾归因"内存提交带宽",因无直接测量支撑本版撤回;本归因为拓扑合理性论证 [S 推论,置信中等],未做 per-core affinity 对照,不排除部分来自内存子系统);
  2. mimalloc 保持 ~4.3× 领先至 8 线程,其每线程堆设计在众核下不退化;
  3. 局限:本测为每线程独立分配/释放(无跨线程 free),跨线程转移行为未覆盖(§9.2)。

5.3 E4 稳态内存与有效内存比 [S]

表 10:E4 稳态内存(数据:E4_*_W3_r{1..5}.json、pressure/E4P_*.json;64MB live、同尺寸换入换出淤积 10s、全页触摸;逐 rep EMR 全披露)

配置live MB稳态 footprint MB稳态开销EMR 中位EMR 逐 rep(P25–P75)加压 E4P(5 reps)
system64.081.9+25.2%0.7990.573–0.815(0.616–0.812)rep 方差极大0.772(0.672–0.857)
jemalloc64.072.5+8.2%0.9240.916–0.929(0.918–0.928)紧—
jemalloc-tuned64.071.0+6.8%0.9360.932–0.940(0.932–0.939)紧—
mimalloc64.075.4+13.4%0.8820.875–0.921(0.875–0.903)紧0.881(0.875–0.921)≈ 无压
mimalloc-tuned64.075.4+14.2%0.8750.868–0.914(0.868–0.895)紧—

注 1:E4P 为 7GB 不可压缩 hog 压力下的重测(v3 修正了 v2 的 E4P 归因错误——v2 的"E4P mimalloc"实为 system 二进制数据,已作废归档于 pressure/superseded/,详见该目录 README;本轮为 bench_mi 真测 + bench system 对照,alloc 字段逐一校验)。 注 2(跨轮漂移声明):mimalloc 默认 EMR 在 round1 为 0.936、round3 为 0.882(−5.4pp);同协议下 mimalloc-tuned 跨轮完全稳定(0.875/0.875)、E4P 压力重测亦为 0.881——该漂移非预热差异(tuned 对照排除)亦非压力所致,成因未证实(候选:round1 当日系统状态),以 round3 数据为当前基准,round1 数据保留备查。 注 3:mimalloc-tuned 开销列由 EMR 0.8753 反推(1/EMR−1);其淤积 footprint 高于 jemalloc 家族,机制假设:立即 purge 使释放页被 decommit,后续同尺寸分配落在新提交页,复用局部性变差 [D 待验证]。

观察:

  1. jemalloc 家族稳态开销最优最稳(+6.8~8.2%,逐 rep 紧凑),约为系统中位数的 1/3 [S];
  2. system 不仅中位最差(+25.2%),rep 间方差也极大(EMR 0.573–0.815,开销 +23%~+74%):magazine 分区高水位收缩行为不可控 [D]——对终端意味着系统分配器的稳态内存行为可预测性差;
  3. mimalloc 默认 EMR 0.882,逐 rep 紧凑,压力不敏感(E4P 0.881)[S];
  4. 同尺寸淤积测的是"元数据+槽位复用"开销;变尺寸碎片行为由 E5 随机序释放间接覆盖,专门实验列为后续(§9.2)。

5.4 E5 峰值后归还(自然归还路径)+ E5P 压力耦合实验 [S]

表 11:E5 归还率(无系统压力条件,空闲内存 ~37%)(数据:E5_*_W2_r{1..10}.json;分配 256MB 逻辑集(实测 footprint 峰值 270–277MB)、全页触摸、随机序全量释放后静置观察 30s;RR 括号为 P25–P75(聚合脚本产出,跨度 >0.02 才标注))

配置峰值 MBfree 耗时RR@0.2sRR@1sRR@5sRR@10sRR@30s
system276.79.6ms0.0000.0000.0000.0000.000 [0.00–0.06]
jemalloc276.53.6ms0.0000.0000.0000.0000.000
jemalloc-tuned276.618.7ms0.9510.9510.9510.9510.951
mimalloc270.59.6ms0.0000.0000.0000.0000.000
mimalloc-tuned270.519.3ms0.9000.9000.9000.9000.900

注(system 逐 rep 全距,min–max):10 reps 中 1 rep(r2)在 5s 内归还 96% 并保持;1 rep(r3)到 30s 仅部分归还(23%);其余 8 rep 全程 RR=0。@30s 的 P75=0.06 即由 r3 拉出——行为由系统内存压力状态决定,见 E5P。

表 11b:E5P 压力耦合对照实验(数据:pressure/E5P_*_W2_r*.json,条件与施压方式见 pressure/MANIFEST.md 与 free_pct.log;施压 = 不可压缩 hog(xorshift 填充,源码 bench/hog2.c);"—"= 语义重复未测)

配置条件RR@30s 逐 rep结论
system无压力(可压缩 hog 被内核吸收,空闲 36–37%;r1–3)0.000 / 0.000 / 0.000不归还
system稳定压力(空闲 26–28%;r11–13)0.962 / 0.961 / 0.952归还 95%+
systemswap 填充极端窗口(r14–15)0.965 / 0.971归还 95%+
jemalloc稳定压力(交错对照 r41–45)0.000 ×5不归还
jemallocswap 填充极端窗口(r1–5 重测批,见注 2)0.954 / 0.960 / 0.961 / 0.954 / 0.963(swap 伪影,见注 2)
mimalloc稳定压力(交错对照 r41–45 + r1–5)0.000 ×10不归还

注 1(交错协议):为排除压力窗口的时间混杂(注 2 的教训),jemalloc/mimalloc 以交错方式(je/mi 交替 r41–45)在同一压力窗口重测——两者同为 0.000,排除"运行顺序恰好"的解释 [S]。 注 2(swap 窗口伪影,诚实披露):jemalloc r1–5 重测批恰逢 hog 初载、内核 swap 快速填充期(swap 6.5/7GB):脏匿名页被换出磁盘(footprint 下降、下降形状与 system 的回收一致、起始点 5 个 rep 精确复现于 1.6s)。这不是分配器归还,而是内核极端压力下的最后手段;iOS 无 swap,此出口不存在——该伪影反而凸显终端语义:macOS 上极端压力最终能压出第三方缓存的内存,iOS 上不能(只能靠 jetsam)。mimalloc 未在等效极端窗口运行,不对其极端窗口行为下结论。 注 3:无压对照(r1–3)的 hog 为 4GB 可压缩填充(0x01 字节),被内核压缩器完全吸收(空闲仅 37%→36%)、未形成回收压力——施压失败的教训本身佐证了 macOS 压力缓冲的层次:压缩器与 swap 先行,可复用页回收在其后 [S]。

图 1:E5/E5B/E5P 归还曲线(assets/e5_return_curves.svg;由 series_mb 全序列生成,横轴秒、纵轴 phys_footprint MB;实线=E5 自然归还、虚线=E5B 显式释放、点线=system 有压对照)

观察与机制(终端场景最关键的一组数据):

  1. 系统的归还是压力自适应的(核心发现):无压力时 footprint 不降(内核没有动力回收已标记 MADV_FREE_REUSABLE 的页——没有回收需求);稳定压力下全部压力 reps 归还 95%+(不依赖 swap 窗口)。对终端的深刻含义:libmalloc 恰好在需要归还的时刻(内存压力上升 = jetsam 风险出现)归还——无压力时的"不归还"无害(无压力即无杀进程风险),有压力时的归还正是生存所需 [S + S 推论];
  2. 第三方默认配置在稳定压力下不归还(jemalloc 5/5(交错)、mimalloc 10/10 reps 为 0.000):其缓存页是脏匿名内存,内核的常规压力响应(回收可复用页)对它们无效;只有 swap 填充期的极端手段才能压出(macOS-only,iOS 不存在)[S]。系统与第三方的差异不是"归还快慢",而是"归还语义"——系统把归还决策交给内核压力机制(页标记为可复用),第三方默认不提供该协议;
  3. 两个 tuned 变体在任何条件下即时归还 0.90–0.95,但代价链:W2 吞吐 −80~−96%(表 8)+ 淤积 EMR 低于 jemalloc-tuned(表 10)[S];
  4. 机制归因 [D]:jemalloc 默认 decay 定时器依赖后续分配事件推进(brew 版 background_thread=0,实证见 verify_jemalloc.err "Background threads: 0");mimalloc 延迟释放队列同样需要后续堆操作驱动。两者在"释放后静置"语义下都不归还(§7.2);
  5. 历史数据修正声明(两处):①round1(v1 文档)中 system "RR@30s=0.961、5s 双峰"实为当时系统压力状态的产物(v1 评委指出双峰异常,E5P 实验给出成因:压力状态调制),round1 数据保留于 data/round1/、不作为 v2/v3 结论依据;②v2 文档的"E4P mimalloc EMR 0.805–0.825 / 条件敏感 0.936→0.882→0.81"为归因错误数据(初版脚本误用 system 二进制,v2 评委 A 溯源发现),已作废归档于 pressure/superseded/ 并以正确双配置重测(表 10 注 1)——真实结论:mimalloc E4 压力不敏感(E4P 0.881 ≈ 无压 0.882)。

5.5 E5B 显式释放通道(内存压力回调路线)[S]

表 12:E5B 显式释放(数据:E5B_*_W2_r{1..5}.json;同 E5 负载,free-all 后立即调用各家族显式释放 API)

配置APIAPI 耗时RR@0.2sRR@30s
systemmalloc_zone_pressure_relief(zone, 0)0.1ms0.0000.000 [0.00–0.12](同 E5 自然行为)
jemallocmallctl("arena.4096.purge")(全 arena)11.2ms0.9510.951
mimallocmi_collect(true)11.5ms0.9970.997

观察:

  1. 显式释放是第三方的"免费午餐":默认配置(吞吐无损耗)+ 压力回调时一次 ~11ms 的 API 调用 → 即时归还 0.95–1.00,无需系统压力配合(与 E5 中系统自然归还的压力耦合形成对照——显式 API 的 madvise/decommit 在调用时刻即从 footprint 移除)[S];
  2. 系统分配器没有等价通道:malloc_zone_pressure_relief 立即返回(0.1ms)且 footprint 无变化——系统的归还只能依赖其压力自适应机制 [S];
  3. 与 tuned 路线对比:E5B 无吞吐代价、归还更彻底(0.997 vs 0.900),是终端集成的明确优选路线。

5.6 E3 延迟分位 [S]

表 13:E3 延迟分位(ns)(数据:E3_*_r{1..5}.json;单线程逐次计时;时间基准粒度 41.67ns(24MHz),p50=0 表示快于一个 tick;快路径精确均值见表 8 的 1/ops/s)

配置负载malloc p50p99p999free p50p99p999
systemW10414104141
systemW20838304183
jemallocW10414104141
jemallocW20125166083125
jemalloc-tunedW10414104141
jemalloc-tunedW2058370801,1661,625
mimallocW10414104141
mimallocW2045858304183
mimalloc-tunedW10414104141
mimalloc-tunedW205,79113,3750411,916

观察:

  1. 所有配置快路径 malloc/free p50 均 <42ns(一个 tick 内)——快路径延迟不构成差异化因素,选择依据应转向吞吐(E1)与内存行为(E4/E5)[S];
  2. 差异化全部在 W2 尾部:jemalloc-tuned free p999 1.6µs(同步 purge 的 madvise 落在 free 路径);mimalloc-tuned malloc p999 13.4µs(purge 后新分配触发缺页批量提交)——与 E1 W2 吞吐跌幅(−80~−96%)交叉印证 [S];
  3. 默认配置的 p999 ≤166ns,尾延迟健康 [S]。

5.7 E6 宏基准(真实应用负载)[S]

表 14:E6 sqlite 宏基准(数据:E6_{sys,je,mi}_r{1..5}.json;sqlite 3.50.4 同源三构建,20 万行混合读写负载(bulk insert + 双索引 + 聚合 + LIKE 扫描 + 半量更新 + 删半回填))

构建wall 中位数 (IQR)peak RSS 中位数行数校验
sqlite-sys1.41s (1.41–1.51)104 MB一致 (200000)
sqlite-je1.41s (1.41–1.44)105 MB一致 (200000)
sqlite-mi1.40s (1.40–1.42)102 MB一致 (200000)

观察(宏基准的交叉验证价值):

  1. 口径与范围说明:E6 采集 /usr/bin/time -l 的 peak RSS(进程外部采样)而非 E4/E5 的 phys_footprint(进程内 task_info)——sqlite shell 无法插入进程内采样点,属声明的口径偏离;RSS 与 footprint 在本负载(无压缩/无 IOKit 映射)方向一致。tuned 变体未入 E6:E6 目的是家族级交叉验证(三构建=三分配器家族),tuned 的代价已在 E1/E3 充分表征,入 E6 只会线性加倍矩阵而不产生新机制信息;
  2. 端到端时间三方持平(±1%):sqlite 负载的时间由 SQL 引擎计算与页缓存主导,malloc 非瓶颈——E1 的 4.42× 微基准差距不会无差别转化为应用级收益,验证了"分配器选型应定位到热点组件"而非整体替换的路线(§8.1)[S];
  3. mimalloc 构建峰值 RSS 最低(102MB,−2MB/−2%),方向与 E4 一致(第三方稳态开销低于系统 libmalloc)[S];
  4. 无任何分配器在真实负载上造成回归(时间与内存均无劣化)[S]——排除了"第三方分配器拖慢真实应用"的反向风险;
  5. 二进制体积增量:+jemalloc.a 537KB / +mimalloc.o 161KB(sizes.json),与 §6.5 一致。

6. 维度分析

6.1 V1 性能

表 15:V1 汇总(数据同 §5 各表,此处为维度视角)

指标systemjemallocjemalloc-tunedmimallocmimalloc-tuned
W1 单线程(相对系统)1.00×1.00×1.00×4.42×4.38×
W2 单线程(相对系统)1.00×0.94×0.20×0.23×0.04×
W1 8 线程(相对系统)1.00×1.02×0.99×4.30×4.20×
8 线程锁退化无无无无无
W2 尾部 p999≤83ns≤166ns1,625ns≤583ns13,375ns

结论(V1 维度):

  1. 小对象密集负载(UI 事件、消息、短字符串——终端最常见形态):mimalloc 显著领先;jemalloc 与系统持平 [S];
  2. 混合尺寸负载(含 ≥64KB 中大对象):系统 libmalloc 领先(jemalloc 0.94×、mimalloc 0.23×);机制假设(libmalloc large entry cache 免除大对象循环的 mmap/munmap [D])待 §7.3 验证;
  3. tuned(常开激进 purge)以 −80~−96% 的 W2 吞吐换取归还,不推荐;归还需求的正确路线是 E5B 显式释放 [S]。

6.2 V2 内存效率

表 16:V2 汇总(数据同 §5,维度视角)

指标systemjemallocjemalloc-tunedmimallocmimalloc-tuned
稳态开销(E4)+25.2%+8.2%+6.8%+13.4%+14.2%
EMR 及稳定性0.799(rep 方差极大 0.57–0.82)0.924(稳定)0.936(稳定)0.882(稳定;E4P 压力下 0.881;round1 曾 0.936 漂移未定因)0.875(稳定)
自然归还 RR@30s(无压,E5)0.000(压力自适应)0.0000.951(即时)0.0000.900(即时)
自然归还 RR@30s(稳定压力,E5P 交错对照)0.952–0.9710.000(5/5 交错)—0.000(10/10)—
显式释放 RR(E5B)0.000(API 空操作)0.951(11.2ms)—0.997(11.5ms)—

注:tuned 变体的 E5B 未重复测试(与其默认配置走同一 purge API,语义相同);"—"= 未测。

结论(V2 维度,终端视角):

  1. 稳态 footprint:jemalloc 家族最优最稳(+6.8~8.2% vs 系统 +25.2%);system 不仅中位最差、rep 间方差也极大(0.573–0.815)——终端可预测性差;mimalloc 稳定(压力不敏感)[S];
  2. 突发后归还的完整图景(本轮核心结论):系统是压力自适应归还(无压不还、稳定压力 95%+);第三方默认稳定压力下不还(jemalloc 5/5、mimalloc 10/10,E5P 交错对照);macOS swap 填充极端期能换出(iOS 无此出口);第三方唯一可靠路线是显式 API(0.95–1.00,~11ms,无需压力配合)[S];
  3. 修复路线对比:常开 purge(tuned)三输——吞吐 −80~−96%、淤积 EMR 反降、归还 0.90;显式 API 路线三赢——吞吐无损耗、即时归还 0.95+、调用成本 ~11ms [S];
  4. system 无快速手动归还通道(pressure_relief 空操作),但其压力自适应机制在终端语义下可能等价够用(无压=无风险)[S + 推论]。

6.3 V3 安全加固 [D]

本维度全部为设计级结论,基于公开文档与源码结构,未实测攻防。

表 17:安全机制对比 [D]

竞品元数据外置freelist 保护UAF 缓解越界缓解随机化加固默认开启
libmalloc部分无无无弱(区布局)✕
jemalloc◎(rtree/edata 外置映射)✕(默认无编码)✕✕○✕
mimalloc△(页首内联)○(secure 模式编码)○(延迟释放降低重用概率)○(secure 模式 guard page)○✕(MI_SECURE 编译开关)
tcmalloc△○(近期版本指针编码)✕✕△✕
Scudo◎◎(带校验和编码链表)◎(quarantine + 独立 region)◎(size class 空间隔离)◎◎ 默认全开
PartitionAlloc◎◎(编码 freelist)◎(quarantine + BRP 可选)◎(bucket 隔离 + guard region)◎◎(Chromium 默认)
snmalloc◎(全外置)◎○◎○✕
hardened_malloc◎◎◎(长 quarantine)◎(guard page 遍布)◎(slab 随机分布)◎

设计级结论:

  1. 加固型(Scudo/PartitionAlloc/hardened_malloc)与通用型(jemalloc/mimalloc/tcmalloc)是两个物种——前者安全默认全开并支付性能/内存代价,后者提供可选开关;
  2. 通用型中 mimalloc secure 模式防御面最完整,jemalloc 优势在元数据外置;
  3. 系统 libmalloc 无系统性加固,对 S3 场景不构成可选方案。

6.4 V4 可观测性 [S+D]

表 18:可观测性对比([S] 为本机接口实测)

竞品统计 API采样 profiling平台工具联动
libmallocmalloc_statistics_t(zone 级)、malloc_good_size [S]MallocStackLogging(env)+ Instruments/malloc_history◎ 原生
jemallocmallctl(分级统计)+ malloc_stats_print [S]opt.prof=true 需编译支持(brew 版未开,实测不可用)[S]文本输出,需自建解析
mimallocmi_stats_print [S] + mi_heap_* APImi_option_verbose;无内置采样 heap profiler同上
tcmalloc✕ 本平台进程不可存活 [S]—(设计级:full 版含 heap profiler)[D]—
Scudo/PA/snmalloc/hm[D] 基本统计或错误报告;PA 依赖 Chromium tracing 生态

实测发现(证据落盘 probe_jemalloc.json):

  1. brew jemalloc 的 mallctl("version") 返回 EINVAL(22),但 mallctl("arenas.page") 正常(16384)——版本 ctl 行为异常值得集成验证时注意 [S];
  2. malloc_stats_print 输出含 "Background threads: 0",实证 §5.4/§7.1 的 background_thread 归因 [S]。

6.5 V5 工程集成 [S]

表 19:构建与接入矩阵(实测)(体积证据:sizes.json)

竞品dylib 体积注入可行(DYLD_INSERT)链接期覆盖状态
libmalloc—(系统)——默认
jemalloc562,704 B✓(导出 malloc/free/mallctl)✓(.a 可用)可用
mimalloc184,608 B(dylib)/ 213,152 B(.o)✗(dylib 不导出 malloc)✓(官方 mimalloc.o,bench 增量 +128,160 B)可用(链接期)
tcmalloc227,136 B✗(启动 SIGBUS)✗(同崩溃)本平台不可用

E6 同源构建增量:+jemalloc.a = +537KB;+mimalloc.o = +161KB(sizes.json)。

接入机制语义差异(框架 §4.7 披露义务):mimalloc 走链接期覆盖,仅替换本可执行文件的符号绑定,动态库内部的分配不受影响;jemalloc 走 DYLD 注入,进程级生效。评估"替换整个 App 分配行为"时两者有差异;对本 harness(自环调用 malloc)测量等效。iOS 通道差异的外推风险见 §9.1 第 6 行。

6.6 设计级集工程性速评 [D]


7. 综合对比与机制归因

7.1 数据 → 架构机制的解释链

表 20:机制归因表

数据现象 [S]机制归因置信度
mimalloc W1 4.42×(270.2M ops/s)free-list 分片:每页独立 free list + 线程本地堆,16–128B 全命中无锁快速路径高 [D](架构公开),量级本机实测
W2 系统 libmalloc 最快(35.97M)libmalloc large entry cache:大对象释放后进缓存直接复用,免 mmap/munmap中 [D],未做 syscall 级计数(§7.3)
tuned W2 掉至 0.20×/0.04×(−80~−96%)常开激进 purge 使大对象释放立即 madvise/decommit,syscall 风暴落在分配热路径高(与默认配置的唯一差异即 purge 参数)[S 推论],E3 尾部数据交叉印证
system E5 归还压力耦合(无压 0.000 / 稳定压力 0.95+,5 reps)libmalloc free 路径将页标记 MADV_FREE_REUSABLE;phys_footprint 仅在内核实际回收后下降,而回收由系统内存压力驱动——页已"可复用",记账等内核高 [S 实验 + D 机制]:E5P 交错对照实验直接证明
jemalloc/mimalloc 默认稳定压力下不归还(jemalloc 5/5 交错、mimalloc 10/10 reps)其缓存页是脏匿名内存(未标记 reusable),内核常规压力响应(回收可复用页)对它们无效;只有 swap 填充期的换出才能压出(iOS 无此出口)高 [S 实验 + D 机制](交错协议排除窗口混杂)
jemalloc 在 swap 填充极端窗口 footprint 骤降(5/5 reps,1.6s 起降)极端压力下内核把冷脏页换出磁盘(非分配器归还);下降形状与 system 的回收一致印证内核侧统一机制中高 [S 数据 + D 归因](swap 使用量旁证)
E5B 显式释放即时生效(0.95–1.00,无需压力配合)purge/collect 走主动 decommit/立即回收路径,调用时刻即从 footprint 移除(区别于系统的被动 reusable 标记)中高 [S 数据 + D 机制细节未逐行核验]
mimalloc E4 压力不敏感(E4P 0.881 ≈ 无压 0.882)(v2"条件敏感"结论为归因错误数据,已撤回)页级 purge 时机不受系统压力调制中 [S 双条件数据]
mimalloc E4 跨轮漂移(round1 0.936 → round3 0.882)成因未证实(tuned 变体跨轮稳定 0.875 排除预热混杂;候选:当日系统状态)低 [S 观察 + D 未定位]
E4 system 逐 rep 方差极大(0.573–0.815)magazine 分区高水位收缩时机不可控中 [D]
jemalloc/mimalloc 释放后空闲 RR=0(无压)页归还由后续分配活动驱动(jemalloc decay 依赖事件推进 + background_thread=0 有 verify 实证;mimalloc 依赖延迟 purge);free-all 后无活动 → 不归还中高 [D+实证]
E4 稳态开销 system 25.2% vs 第三方 6.8–13.4%magazine 按 size class 囤积高水位不收缩;第三方 extent 归还精细中 [D]
mimalloc-tuned 淤积 EMR 低于 jemalloc-tuned(0.875 vs 0.936)立即 purge → 释放页 decommit → 后续分配落新提交页,复用局部性变差中 [D 待验证]
全部竞品 8 线程加速比 4.04–4.29×4P+4E 异构核的算力结构(4×P + 4×~0.3E ≈ 4.1–4.3×),非分配器锁瓶颈中 [S 推论](拓扑合理性论证;未做 per-core affinity 对照,不排除部分来自内存子系统)
E3 全配置快路径 p50 <42ns快路径已近硬件下限(一个时钟 tick 内),分配器差异化在慢路径与内存行为高 [S]
E6 端到端三方持平(±1%)sqlite 负载由 SQL 计算与页缓存主导,malloc 非瓶颈高 [S]

7.2 终端场景的"设计假设错配"与出路

本分析最重要的横断结论:主流第三方分配器为服务器负载设计(持续分配流、进程短命、内存可超卖),而终端负载是"突发后空闲、进程长命、内存即生死"。E5 的 RR=0 现象是这一错配的直接表现——不是 bug,而是设计假设的边界。

本轮 E5P 实验进一步揭示了另一半图景:系统 libmalloc 的"归还语义"是压力自适应的——它把页标记为可复用后交给内核,无压力时不动(无害),压力出现时立即回收(正是需要时)。第三方分配器默认没有这层与内核的协议,其缓存页对内核是普通脏内存,稳定压力下不归还;唯一的例外是 macOS swap 填充期的极端手段(把冷脏页换出磁盘)——iOS 无 swap,该出口不存在,压力终点是 jetsam 而非换出。

出路已由 E5B 数据给出:默认配置保持吞吐与稳态优势,内存压力回调(iOS didReceiveMemoryWarning / macOS memory pressure 源)触发时调用 mi_collect(true)(11.5ms、RR 0.997)或 jemalloc mallctl("arena.4096.purge")(11.2ms、RR 0.951)。该路线相比常开 purge(tuned)无吞吐代价、归还更彻底、无需压力配合(§5.5 对比)。

7.3 待验证机制(后续工作)

  1. W2 大对象路径的 syscall 计数验证(dtrace/dtruss 受 SIP 限制,或改用 kqueue/proc 探针;当前维持 [D] 标注);
  2. libmalloc large entry cache 的存在性与容量(源码级 [D] 核实);
  3. mimalloc-tuned 淤积 footprint 反升的页级追踪验证。

8. 场景化选型建议

8.1 按业务场景

表 21:场景化选型(版本边界:本节结论基于 jemalloc 5.3.1 / mimalloc 3.5.0 / gperftools 2.18.1 / macOS 26.4 libmalloc,跨大版本外推须复测)

场景推荐依据适用条件/前置验证
终端 App 默认分配层(无明显分配热点)保持系统 libmalloc归还压力自适应(E5P 实证:有压 95%+,恰在需要时)、零集成成本、W2 最快、E6 宏基准无回归无
小对象密集热点组件(可独立插拔:编解码/解析/消息)mimalloc(链接期)+ mi_collect 挂压力回调W1 4.42×、8 线程不退化、体积 +161–213KB、E5B 即时归还 0.997、E6 峰值 RSS 最低①组件级隔离(仅热点模块替换)②真机复测倍率与 jetsam 存活 ③Instruments 兼容性
持续分配型后台组件(流式、服务器风格)jemalloc(默认配置 + 压力回调 purge)EMR 0.924 跨条件最稳、统计完善、持续分配下 decay 正常工作组件生命周期内有稳定分配流
安全敏感组件(S3)设计级候选:Scudo / PartitionAlloc加固默认全开 [D]需独立 PoC,本分析数据不足以支撑决策
任何 Apple 终端场景不推荐 tcmallocmacOS 26.4 启动即 SIGBUS [S]除非官方修复并真机验证

8.2 集成风险清单

表 22:集成风险

项systemmimallocjemalloc
替换通道无需链接期(mimalloc.o)——iOS 可用同路径macOS:DYLD 注入或链接期;iOS 仅链接期(§9.1)
符号语义—链接期覆盖不改变动态库内部分配注入为进程级,影响全部动态库
体积增量0+161–213KB(mimalloc.o 213,152 B / bench 链接增量 128,160 B)[S]+562.7 kB(dylib 单文件 562,704 B;静态 .a 另计)[S]
归还风险无(原生)默认不归还;须配 mi_collect 回调 [S]默认不归还;须配 purge 回调 [S]
统计/profilingInstruments 原生mi_stats_print [S]mallctl 体系 [S](注意 version ctl EINVAL 怪癖)
维护成本无跟随上游升级重编同左;MALLOC_CONF 参数面广

8.3 落地前验证清单(真机)

  1. iPhone 真机复测 E1/E5/E5B(倍率、归还行为、mi_collect 耗时;注意真机无 swap、jetsam 阈值更低);
  2. mimalloc purge 调优参数在真机的 RR 曲线;
  3. App 整体(非组件)替换后的 footprint 峰值与 jetsam 存活率 A/B;
  4. Instruments 对 mimalloc 链接期覆盖进程的采样兼容性(MallocStackLogging 对非 zone 分配的可见性);
  5. tcmalloc 最小 PoC(若业务强需求)。

9. 风险与局限

9.1 平台外推风险(逐条)

表 23:外推风险

结论外推至 iOS 真机的风险
mimalloc W1 4.42×A 系列核数/缓存层级不同,倍率可能缩水;方向性排序大概率保持。须真机复测
E5/E5B 归还行为本机有 swap 而 iOS 无——真机高压下"不归还"代价更直接(jetsam);macOS swap 填充期 jemalloc footprint 骤降的出口在 iOS 不存在(表 11b 注 2);libmalloc 归还路径同源(XNU 同家族),方向性结论可信度较高,时序须复测
W2 系统 libmalloc 最快libmalloc 版本与配置随 OS 变化;iOS 与 macOS 的 large cache 策略可能有差异
tcmalloc SIGBUSmacOS 26.4 ≠ iOS 版本,但同为新版 XNU zone 保护机制,风险高度可能迁移;须真机单独 PoC
E4 稳态开销16K 页两平台一致(C4 同源,探测证据见表 2),机制层面可比;量值须复测
DYLD 注入通道 / "iOS 上两者都只能走链接期(mimalloc 路径更成熟)"iOS 无 DYLD_INSERT 通道为平台事实;"mimalloc 链接期更成熟"基于其官方 override 目标(mimalloc.o)是文档化一等公民、且本机实测通过,而 jemalloc 在 macOS 的官方支持路径为 zone 机制 [D]——该比较未经 iOS 真机验证

9.2 覆盖局限


10. 附录

10.1 数据索引

数据路径
微基准原始数据(1M 预热合规,v2 依据)experiments/data/round3/(E1–E5B × 5 配置;system E5 为 10 reps;E3/E4/E5 分别为 50/25/30 文件)
压力耦合对照实验(E5P/E4P)experiments/data/round3/pressure/(E5P:system 5+3 reps、jemalloc/mimalloc 各 5 reps;E4P:mimalloc+system 各 5 reps;条件与施压方式见 MANIFEST.md 与 free_pct.log;作废数据在 superseded/)
过程数据(v1 依据,200K/无预热协议)experiments/data/round1/(含 superseded/ 已声明作废子集)
过程数据(E3/E5B/tuned 行初测)experiments/data/round2/
tcmalloc 失败档案experiments/data/tcmalloc-failure/(attempts.jsonl + 3 份 .ips 崩溃报告)
E6 宏基准experiments/data/round3/E6_{sys,je,mi}_r{1..5}.json
汇总各 round 目录 summary.md / summary.json(中位数+IQR,聚合脚本产出)
探测证据probe_jemalloc.json(mallctl EINVAL/arenas.page)、probe_mimalloc.json(mi_os_page_size)、sizes.json(体积)
归还曲线图assets/e5_return_curves.svg
XNU 源码证据§10.5(xnu-7195.141.2 锚点行号)

10.2 复现命令


cd experiments
clang -O2 -Wall -std=c11 -pthread bench/bench.c -o bin/bench
clang -O2 -Wall -std=c11 -pthread -DUSE_MIMALLOC \
  -I/opt/homebrew/opt/mimalloc/include bench/bench.c \
  /opt/homebrew/opt/mimalloc/lib/mimalloc.o -o bin/bench_mi
./scripts/run_round.sh 3 "all"                                    # E1–E5B 全矩阵
REP_START=6 REPS=10 CONFIGS_OVERRIDE=system ./scripts/run_round.sh 3 "E5"  # system 补 5 reps
./scripts/run_e6.sh 3                                             # E6 宏基准
./scripts/probe_misc.sh 3                                         # 探测与体积落盘
./scripts/run_pressure_test.sh 3                                  # E5P/E4P 压力耦合对照
python3 scripts/aggregate.py data/round3                          # 汇总
python3 scripts/gen_chart.py data/round3                          # 归还曲线 SVG

10.3 竞品 brew 配方编译选项 [S](brew cat 摘录)

竞品brew 配方关键编译参数
jemalloc 5.3.1./configure --disable-debug --with-jemalloc-prefix=(空前缀→导出未前缀 malloc;macOS 无 lg-page 覆盖,自动适配 16K 页)
mimalloc 3.5.0cmake -DMI_INSTALL_TOPLEVEL=ON + 标准 cmake 参数(默认目标含 mimalloc.o 覆盖对象)
gperftools 2.18.1autoreconf + configure(--disable-dependency-tracking 等;本平台不可运行,见 §3.3)

10.4 E6 负载定义

见 experiments/macro/workload.sql:20 万行混合负载(bulk insert + 双索引构建 + 聚合分组 + LIKE 扫描 + 半量更新 + 删半回填 + 终态聚合),每轮独立 DB 文件,行数与字节和校验确定性。

10.5 XNU 源码证据:phys_footprint 即 jetsam 判杀口径 [SRC]

验证对象:本分析 §4.2 指标定义的根基——"phys_footprint 与 jetsam 判杀口径一致"。 验证基线:xnu-7195.141.2(iOS 14.8,Apple 开源分发),文件 bsd/kern/kern_memorystatus.c(存档于 xnu-source-analysis skill 的 multi-version-archive,可第三方复核)。

证据行号内容
kill 路径记账L1636–1642memorystatus_do_kill() 入口即取 footprint = get_task_phys_footprint(p->task),作为 kill 事件的内存度量
memlimit 执法基准L968–969逐进程对比 get_task_phys_footprint 与 task_get_phys_footprint_limit(ledger 限额)
band 内 kill 排序L8091–8100, L8149memstat_asc_cmp() 按页数排序 coalition,页数来自 coalition_get_page_count(各任务 footprint 汇总)
资源准入门控L4718vm_map_fork 以 get_task_phys_footprint 对比系统上限决定是否放行

结论:jetsam 的 kill 选择、限额执法与资源门控均以 get_task_phys_footprint 为口径,与本文 E4/E5/E5B 采集的 phys_footprint(task_info(TASK_VM_INFO))同源——本文"归还率"直接度量的是终端判杀口径下的可回收余量。 版本边界:行号锚定 iOS 14.8 源码;macOS 26.4 / 新版 iOS 的 memorystatus 子系统同源演化(本 skill 六版本存档可见 kill 结构稳定),细节行号必有漂移,口径结论跨版本稳定 [SRC 推论]。

终端设备场景用户态内存分配器竞品分析 · 实验驱动 · 评分迭代 · 数据可溯源