轻重载 · 相机启动速率对比

iPhone 12 Pro (6GB, iOS 14.8) vs HUAWEI Mate 80 Pro (11.7GB + 12GB zswap, HarmonyOS 7) · 同源施压工具 mem_stress -R (随机不可压缩 + 8s 重触) · 档位按剩余可用量对齐 · 基线 n=5, 重载 n=1/档 · ← 返回主报告
+14%
iOS 最大退化
avail 8% 极限档 (549→624ms)
+70~80%
鸿蒙 退化区间
MA 20~21% 档 (801→1435/1363ms)
521MB
iOS 相机存活下限
系统 avail (8% RAM), 仍出画
≈20%
鸿蒙可安全施压下限
受看门狗防线 ABM≈15% RAM 约束

首帧时间: 轻载 vs 重载

轻载 · 基线 (n=5)
iOS 冷启动→首帧
549 ms [534~570]
鸿蒙 冷启动→首帧
801 ms [749~810]
重载 · 中度 1569MB (26%)
iOS 首帧
560 ms +2%
鸿蒙 首帧
1435 ms +79% MA 2599MB (21%)
重载 · 深度 910MB (15%)
iOS 首帧
549 ms +0%
鸿蒙 首帧
1363 ms +70% MA 2362MB (20%)
重载 · 极限 — iOS avail 521MB (8%)
iOS 首帧
624 ms +14%
鸿蒙 首帧
不可安全到达 (看门狗防线 ABM≈15% RAM)
口径: iOS "Preview started"(syslog 收据), 鸿蒙 hilog isFirstFrame(取景器出画) — 与主实验 M3 同源。 两平台档位以"剩余可用量/总内存"百分比标注; 鸿蒙极限档 (≈8%) 位于看门狗防线之下, 不可安全到达。

分阶段退化 (基线 → 重载档)

阶段iOS (基线 → 中/深/极限)鸿蒙 (基线 → 中/深)
系统受理2 → 0 / 1 / 1107 → 147 / 154
应用进程诞生29 → 31 / 35 / 35198 → 264 / 342
应用就绪(onfg)—336 → 511 / 569
首帧 (取景器出画)549 → 560 / 549 / 624801 → 1435 / 1363
鸿蒙退化拆解 (中度档, +634ms): 受理+孵化 +66ms, 应用侧首帧链 +568ms — ballast 逐出文件页后 .so/.hsp 冷缺页重读 + zswap 换入换出 (1.3GB churn) + 重触总线竞争叠加。 iOS 受理/孵化/首帧在 15% 档全部零退化。

总账本: 鸿蒙启动慢在哪里 (基线差距 + 重载放大, 统一分解)

基线: 801ms vs iOS 549ms (+252ms)

层差距trace 证据
① 受理+孵化 (67%, +169ms)T0→进程诞生 198ms vs iOS 29ms贵进门: aa 每次冷启动 fork+exec 新二进制 + binder IPC 链, 107ms 才到 AMS; iOS SpringBoard 常驻 XPC 2ms 受理
② 应用运行时 (33%, +83ms)ArkTS 冷启动风暴重应用: 294 次模块求值 (app 累计 132ms 线程时间, 主线程+WorkerThread 并行) + 运行时初始化/等待 ~320ms; hiperf: jsruntime 60% + 编译 stub 24% + hilog 14% —— 98% CPU 花在引擎与日志而非业务; iOS 原生 UI 无此层
③ 相机管线 (不慢反快)attach 后 ~112ms 拿帧 (iOS 口径 ~520ms)并行式快: 常驻 CameraDaemon + 框架受理即通知, 建管线 (OpenCamera span ~1s) 与 app 孵化/运行时建立重叠 —— 注意不是持久预分配: 会话 ION 池 1.8GB 每次现建, 退出即释放 (实测 1810→176MB 地板)
相机缓冲生命周期实测 (2026-10-13, 双平台空闲→开→关)空闲相机在跑关闭后
iOS mediaserverd footprint39.0MB694.8MB43MB (即释放)
鸿蒙 ION 总量 (IonTotalUsed)176MB1810MB176MB (回地板)
鸿蒙 CameraDaemon RSS109MB221MB109MB
预分配检验结论: 两平台都不做跨启动的持久相机缓冲池——iOS 会话级 IOKit/IOSurface (杀即释放), 鸿蒙会话级 ION (关后 8s 内回地板)。鸿蒙轻载的管线优势来自启动期并行预建 (常驻 daemon + 意图受理即触发, 与孵化重叠), 而非持久池; iOS 则完全内联 (app 自己 openDevice)。早期版本"ION 池 GB 级被压到 207MB/预建池被回收"的表述系口径错位 (拿基线会话期 ION 对比重载启动前 ION), 已修正。
易混淆辨析: 差异不在"预分配", 也不在"分配器效率", 而在"分配通道"。分配快慢不是分配器的固有属性, 是这笔分配要不要等回收让路: iOS 相机缓冲走豁免通道——申请 wired 时腾地方的工作由别人并行代付 (压缩器压别的进程 p3 实测 157K 次/1.4GB、jetsam 杀后台), 申请线程从不排队 (p1 压缩 0 次即满足 ~3.3GB/s 供给); 鸿蒙走普通通道——MA 赤字时每笔 ION 分配都同步等直接回收挤出空间, 需求 1012~1404 MB/s vs 回收 59~62 MB/s (17~24× 失配), 同样的建池工作被拉长数倍。基线时两者都快 (分配器无需等), 鸿蒙墙钟甚至更快 (并行预建掩护, attach 112ms vs iOS 串行内联 520ms); 重载下鸿蒙变慢的不是分配器, 是它排的队。iOS 唯一的例外: 极限档 avail 8% 时 +13% (15 次 buffer 告警)。

重载: +629ms 的放大去向 (与基线同锚点)

放大项Δtrace 证据
① 相机帧交付推迟 (最大单项)+822ms现建分配排队: 会话池 ~1.3GB ION 本就每次启动现建 (基线 t3 窗口也有 7918 个分配事件), 重压下每笔分配都在 MA 赤字里挤回收——同样的工作被拉长数倍 (tp1 窗口 3574 事件), OpenCamera fork+51→fork+248ms, reportOnFirstFrame T0+332→+1154ms
② 孵化更慢+327ms首模块求值 T0+19→+346ms; appspawn/aa 的分配也要挤回收
③ ArkTS 冷缺页+111ms求值 132→242ms, 次数 116→294; .hsp 文件页被逐出后从闪存重读; jsruntime 60%→95%
④ UI 布局 ~7× 放大+299ms (app)app UI 50→349ms (单次最大 4.5×); sceneboard (系统窗口进程) 测量次数 30→245 暴涨 —— 每步布局缺页都从被压扁的 page cache 里挤
进程诞生→首帧 (含内联管线建立)基线轻载 p1中载 p2极限载 p3
iOS (spawn→Preview)520ms529ms514ms589ms (+13%)
鸿蒙 (fork→isFirstFrame)603ms1171ms (+94%)1021ms— (ABM 防线内)
"iOS 口径 ~520ms"即此行基线值 (spawn→Preview)。轻重载答案: iOS 此窗口几乎不动 (轻/中载 ±10ms 噪声内, 极限档 avail 8% 才 +13%) —— 因为相机页 wired/IOKit 豁免回收、回收工作由压缩器并行顶账, 内联管线建立不排队; 鸿蒙同窗口基线 603ms, 轻载即 +94% (预建被回收 + 全链路挤 zswap)。
一句话: 重应用、贵进门、并行式快。iOS 三项全免——XPC 常驻受理、原生 UI、管线内联且 wired 分配豁免回收。 基线差距 252ms → 各自可达极限档 (iOS avail 8%: 624ms vs 鸿蒙 ABM 防线内 20%: 1430ms) 差距拉大到 ~806ms; 鸿蒙到不了 iOS 的 8% 档 (看门狗防线 ABM≈1.8GB 约束施压下限)。(口径: 关键路径数字取锚点单事件墙钟时刻; span 为线程时间含并行; tp1/t3 单轮, 与主实验 n=5 锚点交叉吻合)

启动窗口内存趋势曲线 (取证数据)

iOS p1 · avail (施压 1569MB, 压缩 0 次)
spawnM3 560msT0-0.7sT0+3.6s157098
鸿蒙 p1b · MA (需求 1.4GB/s 砸穿防线)
ABM 1750spawnM3 1562msT0-1.3sT0+4.7s24841285
鸿蒙 p1b · zswap 空闲 (T0 后 0.7s 净换出 880MB)
spawnM3T0-1.3sT0+4.7s86858450
左: iOS avail 在施压 1569MB 下被相机启动直接花到 98MB 谷底, 全程零压缩、首帧不变 (560ms) —— headroom 即弹性。 中: 鸿蒙 MA 以 1.4GB/s 的需求速率砸穿 ABM 防线 (红区), M3 时已在防线之下 ~380MB —— 相机在赤字区出画。 右: zswap 空闲量在 T0 后 0.7s 内跳升 880MB (内核把 ballast 同步压入 zswap 给相机让路), M3 后又被 ballast 重触拉回 (反向排空)。

iOS 供给侧活动量 (T0+2.5s 窗口, 相机栈恒定 cam 24~26 + msdΔ580 + wiredΔ1058~1079MB)

iOS 档avail 施压→谷底压缩次数(2.5s)压缩池Δ缺页首帧
p1 1569MB→98MB0−3MB29K560ms
p2 910MB→54MB12.3K+73MB28K549ms
p3 521MB→8MB157.3K+1422MB75K624ms

鸿蒙 供给速率失配

鸿蒙MA 施压→M3 时→谷底需求吞吃回收追赶zswap 动向
p12566→1368→1137MB1012 MB/s59 MB/s整轮净入 1.3GB
p22345→982→931MB1404 MB/s62 MB/s—
p1b2487→1165MB 谷底~1400 MB/s—T0→+0.7s +880MB (>1GB/s); M3 后 −400~−900MB/s 排空

重载首帧的业务耗时拆解 (trace 取证, tp1 轮 vs t3 基线)

tp1 = 重载 (MA 2453MB) 下 hitrace 9s 全 tag + hiperf 的冷启动轮, 与 t3 基线 trace 同锚点分解。TP1 trace 全程无丢失 (9s 窗口完整覆盖 T0→M3)。

关键锚点 (T0 相对)基线 t3重载 tp1Δ
首个 ArkTS 模块求值 (≈fork+20ms)+19ms+346ms+327ms (孵化变慢)
传感器开启 OpenCamera+249ms+593ms+344ms
应用首帧 UI 上屏 (RS)+344ms+711ms+367ms
相机帧到客户端+332ms+1154ms+822ms
DYTONE 首帧 (M3 口径)+801ms+1430ms+629ms
最大单项: 相机帧交付推迟 ~820ms —— 基线下守护进程的管线建立与 app 孵化重叠, 应用 fork 后 ~112ms 拿到帧; 重压下每次启动都要现建的 ~1.3GB 会话 ION每笔分配都在挤回收 (同样的工作被拉长数倍), 守护进程只能在启动窗口内现场重建: 3574 个缓冲分配事件 (AllocOneBufferLocked×736 / BufferAddressMgr×968), hiperf 中 libc++ 分配器 CPU 占 16.8% (基线不在榜), 传感器开启从 fork+51ms 推迟到 fork+248ms。预建红利在重载下消失。

应用侧 span 分解 (基线 vs 重载)

span (启动窗口, 累计ms / 次数)基线 t3重载 tp1 (Δ)单次最大 ms解读
app · ArkTS 模块求值132 / 116242 / 294 (+111)57.5 → 58.6主线程 163 次 + WorkerThread 94 次 (并行); .hsp 文件页冷读
app · UI 测量12 / 47126 / 199 (+113)11.5 → 52.2app 自身测量
app · UI 布局13 / 9132 / 38 (+119)12.2 → 54.5
app · 脏节点刷新25 / 1091 / 36 (+65)22.3 → 46.4
sceneboard · 窗口测量1 / 3018 / 245 (+17)0.7 → 8.2系统窗口管理端也在重压下反复重排 (次数 30→245)
sceneboard · 窗口布局2 / 726 / 39 (+24)1.1 → 11.8
sceneboard · 窗口脏节点5 / 742 / 39 (+37)2.2 → 13.0
分析方法论 (诚实口径): span 记账基于 ftrace 文本, B/E 事件以线程栈配对 (鸿蒙 E 事件无名字, 必须按 tid 弹栈), 聚合到进程级 (app 10441 / sceneboard 59356 / daemon 1153)。span 是线程时间: ArkTS 求值并行分布在主线程与 WorkerThread, 守护进程重建分布在多个 FFRT 协程线程——累计值含并行, 不可当墙钟相加; 关键路径结论以锚点表 (单事件墙钟时刻) 为准。hiperf 为独立的全系统采样 (hw-cpu-cycles 1kHz, 按进程/DSO 过滤): 应用 CPU 中 libark_jsruntime 60%→95%, daemon 中 libcamera_daemon 29%→41% + libc++ 16.8% (分配器churn)。另有 ~11 次/146ms 模块求值来自窗口内其他进程, 未计入 app 行。首帧净推迟 629ms = 守护交付推迟 (主导 ~822ms) 与应用渲染链推迟 (RS 首帧 +367ms) 的耦合。

三击机理

① 并行预建被重压拉长 (daemon 侧, 主因)

基线: 管线建立与孵化重叠, attach 112ms 得帧。重载: 现建分配排队 (窗口 3574 分配事件, libc++ 16.8%), OpenCamera 推迟 ~200ms, 帧交付 +820ms。

② ArkTS 更慢更重 (应用侧)

app 进程求值累计 132→242ms (+83%), 次数 116→294, 单次最大 ~2×; 求值分布不是单线程——主线程 163 次 + WorkerThread 94 次 + FFRT 线程 17 次 (并行加载), .hsp 文件页被逐出后冷缺页重读。jsruntime CPU 占比 60%→95%。

③ UI 布局测量 ~7× 放大 (app) + 系统窗口 10× 次数 (sceneboard)

app 自身 Measure/Layout/DirtyNode 合计 ~50→349ms (单次最大 ~4.5×), 每步布局缺页都要从被压扁的 page cache 里挤; sceneboard (系统窗口管理, 独立进程) 的测量次数 30→245 暴涨——窗口/启动动画端也在反复重排。应用首帧 UI 上屏 T0+711 (基线 ~T0+344)。

对照组 (iOS 为何免疫)

iOS 相机页 wired/IOKit 豁免回收 + 原生 UI 无 .hsp 冷读 + mediaserverd 缓冲常驻不可逐出 —— 三击全部落空, 首帧 +2%。

猜想验证: 类相机内存申请效率矩阵 (iOS 轻重载是否恒定)

用 alloc_probe (mmap+mlock+wired 逐页写脏, 分相计时) 直接测"类相机" wired 内存的申请速率——四档负载 × 多规模 × 边界/大号轮:

wired 申请速率 (MB/s)128MB512MB大号 (653~896MB)对照 plain
轻载 (avail 1747)539053835581 (896M)5100~5119
中载 (avail 1316)506554945504 (896M)4478~5300
重载 (avail 898)570762185246 (653M)4945~6559
重载 (avail 499)5568——5119 (248M)
边界 (avail 498)——4180 (447M 单发)—
边界 (avail 199, 已持 300MB)—5446 (再 160M)——

大号阶梯 (单发 1~2GB)

单发大号 wired (MB/s)1024MB1280MB1536MB1792MB2048MB
真轻载 (avail 2191~2325)5233589854855226护栏内未测
重载 (avail ~465)15761322987832→ watchdog panic
判定: 猜想证实, 且边界被完整画出。① 供给充足 (size ≤ avail) 时: 轻→重载 (avail 1747→499) 速率完全平坦 (5.0~6.2GB/s; 重载档反而略快——ballast 重触推高 DVFS 时钟, 系统无压力的反证), 128MB~1792MB 规模无关, 累计 wired 747MB 仍全速。 ② 代价归属谜底: 22/24 探针压缩Δ=0、avail 前后 ±2MB——页来自干净文件页直接回收 (零写回/零压缩/零 I/O); avail 不统计 inactive 文件页, 真实供给 = avail + 全部干净文件缓存; 5.5GB/s ≈ 缺页处理速率本身, 瓶颈是 CPU 不是内存系统。 ③ 规模效应只在 size ≫ avail 时出现 (供给须从回收挤): 赤字比 2.2×→1.6GB/s、3.9×→0.83GB/s 优雅降级 (仍为鸿蒙同位置的 13~27×); ~4.4× 撞硬墙——userspace watchdog panic (backboardd/mediaserverd 180s 无法签到, 回收风暴饿死前台守护; panic log 已存档)。对照: C5 相机 p3 (avail 521, 单次启动 wired +1058MB, 赤字比 2.0×) 首帧仅 +14%, 与降级曲线吻合。

因果链: 为什么重载下差距是 +14% vs +70~80%

① 需求侧相当 (差距不在需求)

两平台启动瞬时需求同量级 ~1.4~1.7GB (鸿蒙 ION 预分配+应用, iOS wired 缓冲+mediaserverdΔ+应用); 稳态守护两平台都稳守 (iOS msdΔ 恒定, 鸿蒙 daemonΔ 恒定)。

② iOS 供给: 三级弹性, 全部不在关键路径

headroom 直付 (p1: 压缩 0 次, avail 花到 98MB 仍 560ms) → 轻度异步压缩 (p2: 12K 次) → 压缩器全速并行 (p3: 157K 次 WKdm / 压缩池 +1.4GB, 压的是别人, 相机页 wired 不参与) —— 相机分配从不等待。 回收者全是专用内核线程: jetsam 线程池 (kern_memorystatus.c L1343 jetsam_threads[]) 与压缩器线程 (vm_compressor.c L898) 由水位事件驱动 [XNU xnu-7195.141.2], 且 iPhone 匿名内存无磁盘换页路径 (压缩器即后备存储) —— 申请线程要么直接拿页, 要么等这些并行工作者瞬时补货, 从不自己下场回收。

③ 鸿蒙供给: 单一且同步

MA 被钉死后唯一弹性是 zswap 排水: T0 后 0.7s 内净换出 880MB (>1GB/s); ballast 为随机数据、zstd 无压缩增益 —— 在关键路径上白烧 CPU 搬运数据; MA 砸穿 ABM 585~860MB 进入直接回收。

④ 速率失配 = 量化根因

启动需求 1012~1404 MB/s vs 回收器追赶 59~62 MB/s (1/17~1/24) —— 相机每笔大分配排队等回收挤空间; 应用侧 +568ms ≈ 排队的串行代价。对照组: iOS p3 同样回收了 1.4GB, 只 +75ms (并行+不阻塞+相机页豁免)。
一句话: 重载差异不是"谁更省内存", 而是供给机制 —— iOS 用并行压缩和多级 headroom 把回收挪出关键路径; 鸿蒙只剩同步 zswap 排水, 且排水对象不可压缩, 速率失配 17~24 倍直接计入首帧。M3 后 zswap 反向排空 (ballast 重触迫使换回) 余震持续。取证: iOS camwatch 500ms 页计数器 / 鸿蒙 probe 100ms MA + p1b 轮 ~280ms SwapFree 精采样 (pswp 计数器因 grep 模式尾随空格与 /proc/vmstat 制表符不匹配而缺失, SwapFree 净值曲线有效)。

为什么: 两平台的弹性策略相反

iOS — 杀别人保相机 (免疫的来源)

  • 前台相机高 jetsam 优先级: 轮内系统 avail 回升 +559~632MB (杀后台 + purgeable 回收), 相机足迹全档恒定 (~615MB)
  • 原生 UI 冷启动无需读回大体积代码页; mediaserverd 缓冲按需分配, 仅极限档出现 15 次 buffer 分配失败仍出画
  • ballast (root 进程) 全程存活, 实际牺牲者是被杀的后台应用

鸿蒙 — 三层出血 (退化的来源)

  • 应用层: HHP 巨页 74→6MB 被拆分, 稳态 PSS 204→173/191MB
  • 内核层: 会话 ION 池每次现建, 重压下分配排队 (修正旧口径: 施压轮 ION 快照均为相机关闭时, 不存在"GB 级被压到 207MB")
  • swap 层: zswap 吸收 1.3GB churn, 但代价是启动期换入换出延迟
  • 守护层稳守: daemonΔ 112~131MB 不变 — 退化集中在应用侧冷缺页与 swap 延迟
层iOS (全档恒定)鸿蒙 (基线 → 中/深)
相机应用fp 24~26MB 不变稳态 PSS 204 → 173 / 191MB; HHP 巨页 74 → 33 / 6MB
相机守护mediaserverdΔ 585~591MB 不变daemonΔ 112~131MB ≈不变
内核缓冲池wired/IOKit 映射不可回收会话 ION 池(~1.8GB)每次启动现建、退出即释放; 重压下现建照常但分配排队
系统层让路轮内 avail 回升 +559~632MB (jetsam 杀后台)zswap 吸收 1.3GB churn; 108 条 dma_heap_alloc 告警

极限行为

iOS @ avail 521MB (8% RAM)

首帧 624ms (+14%), 相机存活; mediaserverd 15 次 "Unable to allocate a replacement buffer" (分配失败被吞掉, 取景仍出画); 轮内系统回收 +632MB, 释放 ballast 后 avail 回到 3102MB。

鸿蒙 @ MA 2398MB (20% RAM) — 防线态实测

首帧 1363ms (+70%), 相机存活; 启动期 MA 谷底 931MB (低于动态防线 ABM 861MB, MA<ABM 累计 17.7s, 未触发看门狗); 中度档谷底 1164MB (低于 ABM 590MB, ~1.2s)。更深档 = panic→fastboot 风险, 不做。

协议与口径 (诚实清单)

① 施压: 两平台同源 mem_stress -R (随机不可压缩, WKdm/zstd 均无法吸收) + -k 8 周期重触; iOS 按目标 avail 动态算 ballast (451M/1022M/1976M), 鸿蒙 512M 块 ratchet (4GB/4.5GB) 带 ABM 安全边界 (headroom<900MB 停, <300MB 回滚)。
② 档位语义: iOS avail = free+speculative+purgeable (vm_stat); 鸿蒙 MA = MemAvailable — 均为"系统还能无偿给出的量", 但 zswap 使鸿蒙等量压力需更大 ballast。
③ 不对称披露: 鸿蒙 ballast 体量 (4.5GB, 重触 ≈560MB/s 总线负载) 大于 iOS (≤2GB, ≈250MB/s), 部分鸿蒙退化或来自施压工具自身负载; 但 +70~80% 的幅度远超总线竞争所能解释。
④ n=1/档/平台 (安全与时间约束), 无统计置信; 鸿蒙两档 M3 差 (1435/1363) 在单轮噪声内, 以区间表述。
⑤ 鸿蒙 MA 谷底来自 probe 100ms 采样 (5s 采样器错过谷底); iOS 轮内 avail 轨迹来自 camwatch 500ms 采样。
⑥ 暖启动未在重载下测量; 本页全部为冷启动 (进程重新诞生)。