首次采集缓存相关的 Trace:选择 categories、buffer 大小、时长、adb 命令示例

1. 现象识别:何时需要采集缓存 Trace

在以下场景中,缓存命中率下降是核心嫌疑之一,应当立即启动首次 Trace 采集:

现象典型表现可疑缓存层级
App 启动/页面切换卡顿帧率抖动 < 30fps,CPU 使用率突高但 I/O 低L1/L2 指令缓存、页缓存
多线程竞争场景性能劣化sched_switch 频繁,线程迁移导致缓存污染L2/L3 缓存一致性
内存访问延迟突增perf 采样显示大量 stall 周期所有层级缓存未命中
后台任务导致前台抖动mm_vmscan 事件密集,页缓存被大量回收页缓存 (page cache)
判断规则:如果设备上出现“CPU 繁忙但 IPC 很低(< 0.5)”或“内存带宽高但利用率低”,说明缓存未命中开销已占主导, 必须通过 Trace 量化缓存事件。

2. 数据采集:首次缓存 Trace 参数配置

首次采集的目标是“低成本、全覆盖” —— 用最少的 categories 捕获缓存关键事件,同时保证 buffer 不丢失数据。下面从四个维度逐一展开。

2.1 选择 Categories

下表列出与缓存命中率直接相关的 Perfetto 数据源和推荐类别:

数据源 (DataSource)推荐类别 / 事件覆盖的缓存信息首次是否必选
linux.perf_eventPERF_COUNT_HW_CACHE_REFERENCES (0x2)
PERF_COUNT_HW_CACHE_MISSES (0x3)
CPU 缓存引用/未命中次数必选
linux.ftraceftrace_events: mm_page_alloc, mm_vmscan, sched_switch页缓存分配/回收、调度与缓存热度必选
linux.process_stats(默认开启)进程内存态,辅助判断页缓存归属推荐
android.simpleperf(备选)更细粒度的 PMU 事件矩阵可选(首次暂不加)
首次简化原则:只启用 linux.perf_event(hardware cache 事件)和 linux.ftrace(mm + sched 事件), 避免开启过多 category 导致 buffer 快速写满。

2.2 配置 Buffer 大小

缓存事件产生频率极高(尤其是 PMU 事件),buffer 过小会提前截断。参考以下阈值:

采集场景建议 Buffer 大小说明
首次快速采集(30s)4 MB(4096 KB)平衡丢失风险与资源占用
复测 / 深度分析(60s)8 MB(8192 KB)保证不丢弃 PMU 事件
长时间后台采集(120s+)16 MB(16384 KB)以上需结合频率降低采样周期(period)

2.3 设置采集时长

首次建议控制在 30 秒,覆盖 App 冷启动+首屏渲染+一次用户交互即可。后续可根据问题复现窗口调整:

  • 30 秒:首次基线采集,风险最低。
  • 60 秒:复测验证修复效果,覆盖更多执行路径。
  • 120 秒:排查偶发性抖动,需要配合触发脚本。

2.4 adb 命令执行示例

下方命令使用 Perfetto 文本配置格式,同时启用 PMU 缓存事件和关键 ftrace 事件,输出到设备 /data/local/tmp/:

adb shell perfetto \
  -c - -o /data/local/tmp/cache_trace.perfetto \
  --txt << 'EOF'
buffers: {
  size_kb: 4096
}
data_sources: [
  {
    config {
      name: "linux.ftrace"
      ftrace_config {
        ftrace_events: "mm_page_alloc"
        ftrace_events: "mm_vmscan/mm_vmscan_lru_isolate"
        ftrace_events: "sched/sched_switch"
      }
    }
  },
  {
    config {
      name: "linux.perf_event"
      perf_event_config {
        timebase: {
          period: 1000
        }
        events: [
          {
            type: 0
            config: 0x2    # PERF_COUNT_HW_CACHE_REFERENCES
          },
          {
            type: 0
            config: 0x3    # PERF_COUNT_HW_CACHE_MISSES
          },
          {
            type: 0
            config: 0x0    # PERF_COUNT_HW_CPU_CYCLES (用于计算miss ratio)
          }
        ]
      }
    }
  }
]
duration_ms: 30000
flush_period_ms: 5000
EOF
权限提醒:PMU 事件采集需要内核 perf_event_open 权限。如果设备非 root,确保目标 App 有 profileable 或 debuggable 标识。否则会看到 permission denied 错误, 此时可改用 android.simpleperf 数据源(需 API level 29+)。

3. 原因定位:首次采集后的数据有效性验证

采集完成后,将 Trace 文件 pull 到本地并用 Perfetto UI 打开,按以下规则快速判断数据是否可用:

验证项正常标志异常标志动作
PMU 事件存在在 UI 中搜索“perf_event”能看到 cache-misses 计数完全无 PMU 数据检查权限或改用 simpleperf
buffer 未溢出trace 开头无“buffer overwritten”警告出现“lost events”标记增大 buffer 或缩短时长
ftrace 事件完整mm_page_alloc、sched_switch 可展开事件稀疏或集中在最后几秒增加 buffer 或减少其他 category
首次采集最常见的问题是 buffer 过小导致 PMU 事件丢失。如果发现“lost events”标记,优先将 buffer 翻倍至 8 MB,而不是减少 category。

4. 修复动作:调整采集参数

根据验证结果,对照下表进行针对性调整:

问题调整方案预期效果
buffer 溢出size_kb 翻倍(4096 → 8192)减少 80% 以上丢失事件
PMU 事件无数据改用 android.simpleperf 数据源,配置相同 event id获取等效 PMU 计数
ftrace 事件过多移除 mm_vmscan 子事件,只保留 mm_page_alloc降低 ftrace 写入压力
时长不足以复现问题duration_ms 延长至 60000,同时 period 增大到 2000覆盖完整问题窗口

5. 复测:验证新配置

使用调整后的参数重新执行同一条 adb 命令,再次执行 原因定位 中的验证项。重点确认:

  • PMU 事件覆盖整个时长(而非仅开头几秒)。
  • 缓存未命中率(misses / references)在问题时段有明显波动。
  • ftrace 事件包含 2~3 次完整的 mm 操作序列。

6. 预防:建立标准采集模板

将已验证的配置保存为 cache_first_trace.cfg,纳入团队工具库。以后每次缓存问题排查都以此模板为起点,避免重复调参:

# cache_first_trace.cfg  —— 首次缓存 Trace 标准模板
buffers: {
  size_kb: 4096
}
data_sources: [
  {
    config {
      name: "linux.ftrace"
      ftrace_config {
        ftrace_events: "mm_page_alloc"
        ftrace_events: "sched/sched_switch"
      }
    }
  },
  {
    config {
      name: "linux.perf_event"
      perf_event_config {
        timebase: { period: 1000 }
        events: [
          { type: 0 config: 0x2 }
          { type: 0 config: 0x3 }
          { type: 0 config: 0x0 }
        ]
      }
    }
  }
]
duration_ms: 30000
flush_period_ms: 5000

每次复用模板时,只需修改 duration_ms 和 size_kb 即可适配不同场景。

首次缓存 Trace 采集决策流程 ① 识别缓存问题现象 卡顿 / 高CPU低I/O / IPC低 ② 选择 Categories perf_event + ftrace (mm/sched) ③ 配置 Buffer 大小 首次 4 MB,溢出时翻倍 ④ 选择采集时长 首次 30 秒,复测 60 秒 ⑤ 执行 adb 命令 perfetto 文本配置 + PMU 事件 ⑥ 验证 Trace 完整性 关键检查点 • PMU 事件无丢失 • ftrace 事件覆盖完整 • buffer 无 overwrite
动手建议:将上方 adb 命令直接复制到终端执行,即可获得第一份缓存 Trace。然后用 Perfetto UI (ui.perfetto.dev) 打开, 搜索 perf_event 和 mm_page_alloc 验证数据是否完整。这是后续所有缓存分析的起点。