iOS 相机启动内存实测报告

双场景复测(2026-09-02):后台干净 vs 五大 App 后台 · 整机+进程双账本 · 申请分配效率 · 回收供给效率 · 全计数器合理性
iPhone 12 Pro · A14 · 6GBiOS 14.8(xnu-7195.141.2)16KB 物理页越狱真机 root 实测2026-09-02 21:12–21:16
⚡ 答案速览(TL;DR)——三个最终问题的直接回答
Q1:相机申请多少内存?系统供给多少?哪些内存?

管线需求 ≈1.0GB,与内存环境无关(两场景 Δwired +987MB vs +996MB,差<1%)。归属四份:①内核无主 wired(ISP DMA 环形缓冲/驱动固件)≈375MB;②mediaserverd iokit_mapped(IOSurface 管线缓冲)+612MB;③Camera 壳进程仅 26.1MB;④backboardd 显示侧 +22.9MB。整机抽取:场景一从 free 池抽 -1,639MB(管线+框架缓存副作用);场景二 free 只动 +42MB,全部由回收供给(文件页逐出 -891MB+压缩净得 348MB+purgeable/spec 即摘 ~60MB)。

Q2:启动多快?申请效率多快?free 不足时如何供给?

进程出现→管线内存全部就位 2.04s(场景一)/ 1.77s(场景二),加 SB 派生亚秒级,冷启动到预览稳定 ≈2.1–2.9s。分配机械极快:wire 峰值 3,592MB/s(单 205ms tick +738MB)——慢在管线编排不在分配。free=48MB 时照样 1.77s 就位:回收机器水位驱动,供给顺序 spec/purgeable 即摘(零成本)→ 文件 clean 页逐出 -891MB(≈380MB/s、零 I/O)→ 匿名压缩 +474MB gross(峰值 682MB/s)。jetsam/freeze 全程零触发,五 App 全存活

Q3:各统计值变化与合理性

所有计数器变化均可由机制解释:场景一零压缩零逐出(compressions/purges/swapouts 全程恒定),free −-1,639MB=管线+框架文件缓存(active +521MB、文件页 +262MB);场景二呈镜像结构——free 探底 44MB 不枯竭、压缩器陡涨(stored +1,474MB 全程)、speculative/purgeable 被即摘、reactivations +780MB(框架从缓存直接拉回)。杀相机后 wired bulk 回落(3,505MB/s)+驱动 teardown 尾 ~8s;存活 App 的压缩页不回吐(单向阀)。无泄漏迹象。

本轮复测与 2026-08-29 报告的关系

同一设备同一协议独立复测:管线需求不变量再次成立(Δwired 两轮均在 0.99–1.02GB);本轮新增 ①进程级 8 目标全程 footprint 曲线(250ms)②相机窗口逐出/压缩的分离账本 ③freeze 计数器取证(5 App 阶段冻结 2 进程 +154MB,相机窗口零新增)。结论与前轮一致,量化口径更细。

§0实验设计与方法学

场景一:后台干净场景二:五大 App 后台
前置状态kill -9 全部后台应用(36 进程+补杀),vm_stat 确认 Pages free = 139,208 页 = 2,175MB > 2GB;采样起点 free 2,475MB依序启动 抖音→淘宝→京东→网易云音乐→bilibili(各 20s 间隔,uiopen 拉起),五 App 全部在案后采样基线
相机动作uiopen --bundleid com.apple.camera,ps 尾锚验证进程存活,预览静置 ≥30s(7.2s–43.4s 窗口),随后 kill -9 观察拆除同左(112.3s 启动,150.5s kill;预览静置 33s)
基线水位free 2,475MB(充裕)· level 67%free 97MB(贴地)· level 40% → 相机期 23%

采样器:camwatch(本轮新制探针)EXP

为消除旧方案"每秒 spawn vm_stat 自污染 ~180 页/样本"的问题,本轮用纯内核调用的常驻采样器 camwatch(arm64 CLI,ldid 签名 task_for_pid-allow 等权限):

精度与边界的诚实声明:① uiopen 下发→进程出现的时间受 SSH 链路+Mac/设备时钟对齐(±0.5s)限制,只能给出 ≤0.3–0.9s 的界;进程出现→就位的时间戳全部来自设备自身时钟(精确到采样间隔 200/250ms)。② "进入预览"以内存平台期(wired+mediaserverd footprint 稳定)判定——SSH 上下文无 UI 自动化(zxtouch/WDA 未装),这是等效替代。③ Camera/mediaserverd/backboardd 为平台二进制,vm_region 递归读不到(appscan regions=0),故其构成用 footprint − internal − compressed ≈ iokit_mapped 差分法EST;五 App 的 region 级画像可直读。④ free ⊇ speculative(host.c:815)SRC;jetsam 可用内存公式含 speculative(kern_memorystatus.c:868)SRC

§1场景一:后台干净(free=2,475MB)冷启动相机

场景一全程时间线

图 1-1 场景一全程(85s,200ms/点)。wired 从 795MB 抬到 1,782MB(Δ+987MB);free 从 2,475MB 降到 836MB(Δ-1,639MB);mediaserverd footprint 34→731MB。杀相机后 free 全额回位。

场景一启动微观

图 1-2 启动微观(4.5–9s)。三段式:①壳进程加载(Camera fp →26MB)②mediaserverd 建链(iokit 映射涌入)③集中 wire:单 205ms tick 内 wired +738MB(3,592MB/s)。

场景一拆除

图 1-3 杀相机后的回收(43–52s)。kill 后 ≤200ms 进程消失,wired bulk −906MB/202ms;mediaserverd 678→46MB;随后 ~8s 驱动 teardown 慢尾把 wired 补回基线。

整机计数器账本(基线 → 预览平台期)EXP

计数器(vm_stat)变化机制解读
Pages wired down+987MB相机管线主体:ISP DMA 缓冲+IOSurface 锁页+驱动固件结构(Q1 详拆)
Pages free(含 speculative)-1,639MB充裕环境直接从 free 池抽取;回收机器纹丝不动
Pages active+521MB相机/mediaserverd 框架文件页+管线用户态结构进入活跃队列
Pages inactive+142MB启动过程置换出的冷页入 inactive
Pages speculative+88MBfree 充足时预读大胆落 bins(对照场景二被即摘)
Pages purgeable / purges+18MB / +8MB无需丢弃任何可清除页
file-backed pages+262MB框架/资源文件页缓存增长(启动的副作用,非管线本体)
anonymous pages+489MBmediaserverd 内部堆(15.7→108MB)+Camera 壳 18MB+系统进程伴随增长
compressions / decompressions0 / +42MB零压缩——这是"free 充裕则压缩器不劳动"的直接证据;decompressions 为系统进程触碰旧压缩页的背景噪声
pageins / pageouts / swapins / swapouts+242MB / 0 / 0 / 0只读入不换出;启动读入即相机框架代码与资源
reactivations+0MB≈0:free 充裕时无需从 inactive 拉回
场景一要点:供给方式=直接抽取 free 池。相机管线 1GB+框架缓存副作用 ~0.6GB 全部由 -1,639MB 的 free 落差买单,压缩器、逐出、purgeable 丢弃、swap、jetsam 全部零参与。启动窗口内 compressions/purges/swapouts 三个累计计数器一字不动——回收机器"机制常驻、劳动按需"的最干净对照。

§2场景二:五大 App 后台(free=97MB)冷启动相机

场景二全程时间线

图 2-1 场景二全程(185s,250ms/点)。五 App 依序启动把 free 从 2,192MB 压到 97MB;压缩器(右轴色)同步吃进后台 App 驻留页;相机启动(112.3s)与 kill(150.5s)的 wired 起落。

2a. 五 App 就位阶段(0→100s)EXP

计数器变化(pre→相机前基线)解读
Pages free-2,096MB2.2GB 被 5 个重 App 吃光(抖音 567 / 淘宝 320 / 京东 146 / 网易云 350 / bilibili 358 峰值 footprint,合计 1,741MB)
compressions(累计)+1,474MB后台化 App 的驻留匿名页被渐进压缩(淘宝 in≈0.4MB 几乎全压缩;抖音 compressed 434MB)
Pages occupied by compressor+394MB压缩器占用净增;全程序压缩比 ≈2.9:1(stored 内容量/占用)
swapouts+157MB≈freeze_pageouts 增量 9,869 页(154MB)——freezer 冻结 2 个后台进程落盘(freeze_count 0→2),非传统换出
pageins / reactivations+2,906MB / +1,457MB五 App 冷启动读入+相互顶替时的缓存回拉
file-backed / anonymous+323MB / +957MBApp 代码资源缓存+用户态堆驻留

2b. 相机启动窗口(112.3→114.1s):free=48MB 供给 1GB 的全账本EXP

场景二相机窗口

图 2-2 相机窗口微观(110–122s)。wired +996MB 与压缩量陡涨同步;free 探底 44MB 不枯竭(供给跟上了分配)。

供给来源(回收侧)成本/速率
文件页逐出(file-backed)-891MBclean 页零 I/O 直接回 free;≈380MB/s 持续
匿名压缩(compressions)+474MB gross峰值 682MB/s(单 tick);净得 348MB(压缩器占用 +126MB)
purgeable 丢弃-37MB≈0 成本即摘(网易云 volatile 12MB 等)
speculative 摘除瞬时 −23MBspawn tick 内即摘;随后相机预读又回填 +61MB(净 +61MB)
inactive / active 队列-620MB / -538MB队列腾挪:冷文件页出队+框架热页经 reactivation(+780MB)直接复用缓存
未动用的手段jetsam 0 次 · freeze 0 次新增 · swap 0页级腾挪足够,无需进程级献祭
五App内存形态迁移

图 2-3 五 App 在相机窗口的形态迁移:蓝(驻留匿名)→紫(已压缩)。bilibili internal 278→152MB(其中 ~33MB 被直接丢弃:reusable/purgeable 路径),网易云 216→187MB;淘宝在基线前已被压干(in≈0)。

2c. 五 App 进程账本(footprint / KB→MB)EXP

Appfp·基线internal·基线compressed·基线fp·预览后internal·后compressed·后Δfp
抖音5668943456648476+0
淘宝31503003150300+0
京东138104341388949+0
网易云29821693298187121+0
bilibili279278024615293-33

五 App footprint 合计 1,597→1,564MB:压缩只改变形态(驻留→压缩)不改变记账;净 fp 变化 −33MB 全部来自 bilibili 的可丢弃页。相机杀掉后五 App 全部存活(survivors.txt)。

2d. 杀相机拆除(150.5s)

wired bulk 回落 -1,015MB(峰值 3,473MB/s),mediaserverd 642→50MB,free 回 +1,239MB;压缩器占用 −-29MB(死会话压缩页直接摘除,不经解压),但存活 App 的压缩页不回吐(compressions 只增不减的单向阀)。拆除期 pageins +102MB——系统进程回拉缓存。

Q1相机启动会申请多少内存?系统需要供给多少?分别是哪些内存?

账本一:进程视角(谁在申请)EXP

归属场景一场景二内容
内核无主 wired≈375MB≈471MBISP DMA 环形缓冲、驱动固件结构、新映射页表——只进全局 wired 计数器,任何进程 footprint 都看不见
mediaserverd iokit_mapped+612MB(1.9→614)+525MB相机管线真正的主人:AVFoundation 服务端的 IOSurface/DMA 缓冲(三方共享:App 绘制/GPU 渲染/ISP 写入)
mediaserverd internal+92MB(15.7→108)+管线编排的用户态堆
Camera 壳进程26.1MB(internal 17.9MB)24.2MBUI 壳:预览取景器只是管线的"遥控器"
backboardd 显示侧+22.9MB+15.2MB帧提交/显示合成路径
合计(管线需求)≈1.05GB≈1.03GBΔwired +987/+996MB 为上界口径(iokit⊂wired 有重叠,见注)
管线需求不变量:两场景 Δwired 差 <1%(+987 vs +996MB)。相机管线的需求量由会话配置(分辨率/格式/缓冲深度)决定,与内存环境无关——free 只剩 48MB 照样拿到全款。iokit⊂wired 的重叠拆分依赖"mediaserverd 的 IOKit 映射全部 wired"这一合理假设EST,总量口径(Δwired)不受影响。

账本二:整机视角(系统实际供给)EXP

回答"哪些内存"的三层结论:①形态——wired(不可压缩/换出/丢弃,DMA 刚性)为绝对主体(>90%),少量匿名堆,几乎无文件页;②归属——内核无主账+mediaserverd 为主、Camera 壳极小("进程账极小、内核账极大"的极端案例);③获取路径——IOKit 预装配(IOSurfaceCreate 返回时全部就位),不走 CPU 缺页懒分配。

Q2相机启动耗时多长?涉及内存的申请效率有多快?free 不足时如何回收供给?

启动耗时链条EXP

阶段场景一场景二说明
uiopen 下发 → 进程出现≤0.3–0.9s≤0.3–0.9s受 SSH 链路+时钟对齐(±0.5s)限制只能给界;SpringBoard 派生本身亚秒级
进程出现 → 壳加载完成~0.8s~0.6sCamera fp 爬到 ~25MB(dyld+框架)
进程出现 → 管线内存全部就位2.04s(wired 达平台 99%)1.77s含 mediaserverd 建链+DMA wire+IOSurface 映射
总计(下发→预览稳定)≈2.1–2.9s≈2.1–2.7s"预览稳定"以内存平台期判定(方法学声明见 §0)

申请分配效率EXP

操作实测速率含义
wire 分配(峰值)3,592MB/s(S1)/ 1,897MB/s(S2)分配原语本身极快——"wired 分配慢"是误解;S2 峰值略低是回收供页的节奏,不是分配慢
管线整体就位1GB / 2.04s ≈ 500MB/s 平均瓶颈在管线编排(DART 映射/驱动会话协商),不在页分配
mediaserverd iokit 涌入~450MB/s(fp 曲线斜率)IOSurface 批量映射
环境对比S1 2.04s vs S2 1.77sfree 48MB 与 free 2.4GB 的就位时间同量级——回收供给对启动速度无可感拖累(本轮 S2 甚至略快,属轮次方差)

free 不足时的回收供给机制(场景二实测)EXP

不是预案,是水位驱动的流水线。相机启动把 free 砸到警戒线附近(探底 44MB),回收机器按成本阶梯依次供页:

顺位手段本轮实测成本
1speculative 摘除spawn tick 内 −23MB≈0(预读赌输的页,零 I/O 丢弃)
2purgeable 丢弃−-37MB(purges +12MB)≈0(volatile 页直接扔)
3文件 clean 页逐出-891MB / 2.3s零 I/O(脏页才需回写,本轮 pageouts +860 页仅背景噪声)
4匿名压缩gross +474MB(峰值 682MB/s)CPU 换内存(净得 348MB)
5freeze(冻结落盘)相机窗口 0 新增(五 App 阶段已冻 2 进程 154MB)I/O,按需后台执行
6jetsam(杀进程)0 次进程献祭——页级腾挪够用时根本轮不到
关键证据链:①free 探底 44MB 但从未枯竭(供给速率 ≥ 分配速率);②water level 40%→23% 期间 compressions 陡涨 +474MB 与 wired 上涨+996MB 同窗口发生;③五 App footprint 全程可见且无一死亡;④swap/jetsam 计数器零增量。"先开多个大 App 再开相机易触发回收"的机理=此流水线。

Q3各内存统计值变化情况与合理性分析

统计值场景一(free 充裕)场景二(free 贴地)合理性判定
Pages free-1,639MB(含 spec +88)+42MB(探底 44MB 后回升)✓ 两场景语义一致:充裕时是"水源",紧张时是"水位计"——只反映池子余量,不反映供给能力
Pages speculative+88MB(大胆预读)瞬时 −23MB 后回填 +61MB✓ 与 free ⊇ speculative 的口径一致(host.c:815);"带着收益的 free",压力时第一个被摘
Pages wired down+987MB+996MB✓ 相机场景的主科目;两场景差<1% 证明管线需求不变量;wired 是"时变池"而非静态基线
Pages purgeable/purges+18MB / +8MB−-37MB / +12MB✓ 充裕时增长(缓存可丢则丢的自愿登记),紧张时即摘
file-backed+262MB(框架入缓存)-891MB(最大供给源)✓ 同一科目两种角色:无压力时是缓存堆积,有压力时是第一提款机
anonymous+489MB-206MB(相机增量被后台压缩抵消)✓ 净额=新增 − 被压缩移出,需与 compressions 联读
compressions/decompressions0 / +42MB+474MB / +36MB✓ 累计型单调计数器;场景一零压缩是"够用就好"的直接证据
Pages in compressor-9MB+126MB(杀相机后 −-29MB)✓ 水位类;死会话压缩页直接摘除,存活 App 压缩页不回吐(单向阀)
reactivations+0MB+780MB✓ 场景二大量回拉=框架代码页从 inactive 缓存直接复用(省 pagein);对应 pageins 仅 +194MB
pageins/pageouts/swap+242MB / 0 / 0+194MB / +860 页 / 0✓ 逐出 clean 文件页零 I/O;swapouts 增量全部来自 freeze 落盘(非传统换页)
kern.memorystatus_level67%(全程稳定)40%→23%(相机期)→46%(杀后)✓ 水位百分比与 free/可用页走向吻合;23% 仍未进 warn 带(kevent 零事件可佐证)
两条解读纪律(避免误读统计值):①队列账 vs 内容账正交——active/inactive/speculative/free 按"在哪个队列"记账,file-backed/anonymous/compressor 按"是什么内容"记账,两套有重叠,不能混加;②水位类 vs 累计类分开读——free/compressor pages 是瞬时水位(进程退出会回吐),compressions/purges/pageins 是终身累计(只增不减)。场景一的"compressions 恒定"与场景二的"compressions 陡涨"对比正是水位驱动状态的开关证据。

§5效率汇总:申请分配 × 回收

操作实测效率场景
wire 分配(峰值 burst)3,592MB/s(+738MB/205ms)S1 冷启动
wire 分配(压力下峰值)1,897MB/sS2(回收供页节奏)
管线整体装配~1GB/2.04s ≈ 500MB/s两场景同量级
spec/purgeable 即摘≈0 成本(单 tick 内)S2 spawn 瞬间
文件 clean 页逐出≥380MB/s 持续(-891MB/2.3s)S2 相机窗口
匿名压缩(burst)682MB/s(净收益按 2.9:1 打折)S2 相机窗口
freeze 落盘154MB(后台慢速执行)五 App 阶段
拆除:wired bulk 回收3,505MB/s(−906MB/202ms)kill 后第一 tick
拆除:mediaserverd 卸载678→46MB / ~600mskill 后
拆除:驱动 teardown 尾~8s 补完最后 ~100MBkill 后
拆除:freeze/jetsam/swap0 参与全程
效率结论:回收成本阶梯 spec/purgeable 即摘(≈0)< 文件 clean 逐出(零 I/O,380MB/s+)< 匿名压缩(CPU 付费,burst 682MB/s)< freeze(I/O)< jetsam(进程献祭)。iOS 相机场景的压力供给在第二、三级就完成了全部工作——这是"重 App 后台堆叠时开相机依然流畅"的内存侧解释。

§6方法学细节 · 数据完整性 · 原始数据

实验执行记录

  • 2026-09-02 21:12:38–21:15:44(本机时间),设备解锁态全程验证(实验前后 appstate 均为 NO)
  • 场景一前置:杀 36 个后台应用进程(+补杀 1 残留),vm_stat 确认 Pages free=139,208 页=2,175MB>2GB 后方启动相机
  • 场景二:5 App 依序 uiopen,各 20s 间隔,存活验证全部通过(pid 由 camwatch 流实时确认)
  • 相机两次均以 kill -9 结束(模拟最强拆除路径),拆除后 survivors 检查:五 App 全存活、Camera 已死
  • CrashReporter 取证:实验窗口内零 JetsamEvent(最近一条为实验前 4.5 小时)

已知局限(如实标注)

  • uiopen→进程出现的时间界受 SSH 链路与 Mac/设备时钟对齐(±0.5s)限制
  • "预览就位"以内存平台期判定,非 UI 事件(SSH 上下文无 UI 自动化)
  • 平台二进制(Camera/mediaserverd/backboardd)region 不可读 → iokit 用差分法估算
  • kevent MEMORYSTATUS 未触发(未进 warn 带),压力过程以 level 列为准
  • 单轮实验(每场景一次);与前轮(2026-08-29)同协议互证,关键不变量两轮一致

原始数据与工具(本站数字的可追溯来源)

文件内容
data/s1_timeline.txt / s2_timeline.txtcamwatch 全程时间线(423 / 735 个采样点,含元数据头)
data/s1_markers.json / s2_markers.json编排标记(uiopen 下发/返回、pid 首见、kill、时钟漂移)
data/s1_pre|post_vmstat.txt, s2_pre|baseline|post_vmstat.txtvm_stat+freeze 计数器快照(阶段锚点)
data/s2_baseline_appscan.txt五 App region 级画像(相机启动前)
data/s1_killed_procs.txt, s2_survivors.txt, s2_crashlog_recent.txt前置清理、存活与 jetsam 取证
ios-probe/cli/camwatch.c采样器源码(55 列 TSV 协议见文件头)
run_s1.py / run_s2.py / analyze.py / build_charts.py编排与分析全链路脚本
实测环境:iPhone 12 Pro(iPhone13,3)· A14 · 6GB · iOS 14.8(Darwin 20.6.0, xnu-7195.140.44~1)· Taurine 越狱 · 16KB 物理页。
证据分级:[EXP] 本轮设备实测 · [EST] 结构估算 · [SRC] 源码行号锚点。姊妹报告:iOS 内存管理深度剖析(主书) · 前轮相机报告(2026-08-29,同协议独立复测互证)。生成:camwatch 探针+paramiko 编排,全程零人工介入设备。