| 场景一:后台干净(free 2.4GB) | 场景二:五大 App 后台(free 48MB) | |
|---|---|---|
| 相机申请(Δwired) | +987MB | +996MB |
| free 池变化 | −1639MB(管线+框架缓存副作用,直接抽取) | 仅 −42MB(几乎全部由回收供给) |
| 回收机器动作 | 零参与:压缩/逐出/purgeable/jetsam 计数器一字不动 | 文件页逐出 891MB + 匿名压缩 474MB(毛额)+ purgeable/spec 即摘 ~60MB |
| 启动→就位 | 2.04s | 1.77s(同量级,无可感拖累) |
这 1GB 去了哪里:内核无主 wired ≈375MB(ISP DMA 环形缓冲、驱动固件——任何进程账都看不见)+ mediaserverd iokit_mapped +612MB(IOSurface 管线缓冲,真正的主体)+ Camera 壳进程仅 26MB(UI 壳只是管线的"遥控器")。EXP
| 顺位 | 手段 | 实测 | 成本 |
|---|---|---|---|
| 1 | speculative / purgeable 即摘 | ~60MB,单 tick 内 | ≈0 |
| 2 | 文件 clean 页逐出 | 891MB / 2.3s ≈ 380MB/s | 零 I/O(纯队列操作) |
| 3 | 匿名页压缩 | 474MB 毛额,峰值 682MB/s | CPU 换内存 |
| 4 | freeze(冻结落盘) | 相机窗口 0 新增 | I/O(五 App 阶段已后台完成 154MB) |
| 5 | jetsam(杀进程) | 0 次 | 页级腾挪够用时轮不到 |
系统没有为相机杀任何进程,五个 App 全部存活。free 探底 44MB 从未枯竭——供给速率始终跟得上分配速率。
IOKit wire 路径(vm_object_iopl_request,vm_pageout.c:6036–6067)拿页只有三步:
vm_page_grab_options() 从 free 池拿一页VM_PAGE_WAIT() 睡觉(登记等待者+唤醒回收 daemon)展开后的 vm_page_wait(vm_resident.c:3813)没有一行代码去做扫描/逐出/压缩。防死锁配套:free 池底部的保留池只留给回收机器自己(TH_OPT_VMPRIV,vm_resident.c:3175)——保证生产者永远能拿页继续干活。
| 线程 | 干什么 | 特权 |
|---|---|---|
vm_pageout_scan | 文件页逐出(零 I/O)、丢 purgeable、把脏匿名页挂压缩队列 | BASEPRI_VM=91(用户前台 QoS 最高才 47)——抢占一切用户态 |
VM_compressor ×2 | 从队列批量取页压缩,32 页一批归还 free 池 | 优先级 91 + 绑定 E 簇(能效核)——实测压缩爆发期间性能核全程空闲 |
相机启动第一个 250ms 窗口:wire 爆发 1897MB/s 的同一窗口,供给(文件页逐出 1324 + 压缩 682)= 2006MB/s 同步开动。free 探底 44MB 后,在 wire 仍在爬坡的最猛阶段不降反升,回到 126MB——供给侧追平并反超了消耗,锁页线程全程没有真正饿到。
失败模式是"慢"不是"崩"(本轮均未发生):锁页线程睡觉等页 → 代价是相机启动变慢(不是失败)→ 优先级 91 的生产者全速补货 → 仍不够才 jetsam 杀后台兜底(零触发)。
| iOS (XNU) | Linux | |
|---|---|---|
| 执行位置 | 全部在专用内核线程(优先级 91、绑 E 簇):申请者从不做回收苦役 | 直接回收在申请者自己的上下文同步执行(try_to_free_pages,vmscan.c:3233)——同一个线程既当消费者又当生产者,这就是 direct reclaim 停顿的根源 SRC |
| 后台线程 | 2 个高优先级压缩线程 + scan 线程 | kswapd 每 NUMA 节点 1 个,普通优先级、不绑簇(vmscan.c:4043) |
iOS(vps_choose_victim_page,vm_pageout.c:2331)SRC:按成本物理分队列,固定瀑布 cleaned(刚洗净)→ 投机型页(预读从未触碰,LRU 之外弹队列即回收)→ 文件页 → 匿名页,裁决全部偏向文件页:
Linux(get_scan_count,vmscan.c:2237+)SRC:swappiness × refault 成本反比加权的比例模型——追求全局回收代价最小(哪边 refault 少多压哪边)。告急时 iOS 行为完全可预测(文件页先扛),Linux 取决于当时的统计。
| iOS | Linux | |
|---|---|---|
| 匿名页 | 压缩机内建,无条件可回收 | 必须配置 swap/zram,否则匿名页完全不回收(vmscan.c:2250)——"先堆五个大 App 再开相机"的局,默认 Linux 连压缩这一级供给都拿不出来 |
| 压缩算法 | WKdm 手写汇编(单核 ~780MB/s)+MZV 单值页 4 字节编码+早退检查点+LZ4 择优 | zram 默认 lz4(单核速度同量级或更快);同值页检测需线性扫描全页 GEN |
| 各领先的项 | 投机型页快车道(免引用检查)、死文件免二次机会(vnode isinuse)+对象级整体逐出 | workingset refault 距离:逐错保护更精确(iOS 只有引用位粗判);6.1 MGLRU 加速扫描 |