1. 缓存命中率低的典型现象

当系统或应用的缓存命中率长期处于低位时,CPU、内存和I/O 子系统之间会频繁发生“缓存未命中→ 主存/磁盘加载”的慢路径操作。这种慢路径在用户端会叠加出若干可感知与可测量的性能异常。本章从工程师视角归纳这些现象,并为后续使用 Perfetto 抓取证据提供识别锚点。

1.1 现象清单与特征描述

现象 特征描述 排查方向 影响范围
应用卡顿 列表滑动不跟手、过渡动画掉帧、点击后延迟响应 UI 线程等待内存/磁盘加载 前台应用
帧率抖动 Profiler 曲线频繁出现≥ 16ms/33ms 单帧耗时尖刺 GPU 或 SurfaceFlinger 因缓存未命中而阻塞 渲染管线
页面加载慢 Activity/Fragment inflate 、网络数据解析、图片解码时间过长 资源缓存与对象缓存失效 应用冷/热启动
ANR 出现 AMS 检测到主线程超时(5s Broadcast/20s Service/200ms Input) I/O 或内存访问堆积导致主线程阻塞 全局体验
系统 CPU 异常高 CPU 使用率长时间 > 80%,且 kswapd/irq 等内核线程活跃 缓存未命中引发大量 TLB miss 和缺页中断 系统整体功耗 & 散热

1.2 现象关联故障树

下面的故障树展示了缓存命中率低如何逐层传导为用户侧可感知的性能症状。每层节点都对应 Perfetto 中可观测的 trace 指标。

缓存命中率低 → 用户感知现象 故障树 缓存命中率低 L1/L2 频繁 Miss TLB 抖动 缺页 / IO 等待 帧率抖动 应用卡顿 系统 CPU 异常高 应用卡顿 页面加载慢 ANR 出现 用户体验劣化 故障树节点均可通过 Perfetto trace 直接观测

1.3 现象-排查匹配表

在实际排查中,同一个现象可能由多个缓存层级导致。以下匹配表帮助你在选择 Perfetto 分析目标前快速收敛范围。

现象 首要怀疑层级 次要怀疑层级 Perfetto 初步数据源
帧率抖动 L1/L2 cache(CPU 流水线 stall) GPU cache / System cache CPU frequency + cache-misses 计数器
应用卡顿 TLB / page-table walk I/O 等待 sched_switch + page_fault
页面加载慢 文件系统缓存 / page cache 应用对象缓存 f2fs/ext4 事件 + iostat
ANR 缺页中断 / major-fault storm 锁竞争 + 缓存 miss am_anr + sched_blocked_reason
系统 CPU 异常高 TLB shootdown + cache coherency IRQ 处理 irq_handler_entry + cpu_idle

1.4 判断规则

  1. 规则一(时域规则):如果帧率抖动与 CPU 频率尖峰同步出现,且频率尖峰前存在一段 cpuidle 活跃片段,优先怀疑 CPU cache miss。
  2. 规则二(频域规则):如果 ANR 发生前 2 秒内 pagefault 事件数量 > 1000 且 major_fault 占比 > 30%,缓存命中率极低是直接原因。
  3. 规则三(对比规则):在相同场景下,对比打开/关闭 HWUI 硬件加速的帧率曲线,若关闭后抖动消失,通常指向 GPU cache miss。
  4. 规则四(阈值规则):Perfetto 中 cache-references / cache-misses 比值 < 0.9 即进入危险区;< 0.7 时几乎必然出现用户可感知卡顿。

1.5 快速自检清单

在进入下一章的数据采集之前,请对照以下清单确认当前问题是否匹配缓存命中率低特征:

  • ✓ 用户反馈包含“滑动卡”、“点不动”、“白屏久”等描述
  • ✓ 系统日志中出现 InputDispatcher: Timed out waiting for focus
  • ✓ 通过 dumpsys 观察到 pagecache pressure 或 kswapd0 持续激活
  • ✓ 在没有高 CPU 负载的应用中,CPU 频率频繁冲到最高档位
  • ✓ 复现时设备温度快速上升(伴随 CPU 持续高频率)
排查技巧:如果遇到偶发卡顿,建议先用 adb 持续抓取 30 秒 trace(包含 -a -b 30000 cpu freq 等类别),然后通过“现象 → 时间戳”在 trace 内精确锚定异常窗口。不要仅靠肉眼观察反复复现,那样会浪费大量时间。

adb shell 一键抓取步骤(供本章快速验证使用):

adb shell perfetto -c - -o /data/misc/perfetto-traces/trace.perfetto \
  --txt -t 30s <