Home > IT > Article

Android Perfetto 系列 12:Trace 数据流与丢GA排查

2026-10-30  ·  Views: 430

共享内存还有一个容易漏掉的数字:默认大小是 256KB,官方经验范围大概是 128-512KB。这个大小应付普通切片通常够用,但扛不住“大包突发”。官方文档举过截图类统计结果源的例子:Draw均写入速率看起来不高,但一次性写入 2MB 时,瞬时写入速度会远超 traced 搬运速度。

处理顺序建议这样排:

  • 降低事件密度。热循环里不要每次迭代都打 Track Event。
  • 拆小超大事件。单个大包容易撑爆共享内存。
  • Perfetto SDK producer 可以评估 shmem_size_hint_kb 或 producer shared memory 大小。适用topics件是确认瓶颈来自 producer 侧突发,而不是 central buffer 覆盖。
  • BufferExhaustedPolicy::kStall 可以避免直接丢包,但会让 producer 在 buffer 耗尽时等待。只有确认这类阻塞开销可接受时,才适合用它保护关键事件。

这部分会在第 13 篇 App 侧 Track Event 与现场 Trace 里展开。业务埋点越密,越需要控制事件密度、单包大小和 producer 侧 backpressure 策略。

central buffer 丢GA:Ring 覆盖或 Discard 丢新数字

TraceConfig 里的 buffers 是 central buffer。这里有两种常见丢GA,排查时提议直接看统计项名字,不要只依赖 severity Category:

  • traced_buf_chunks_overwritten:RING_BUFFER 写满后覆盖旧统计结果。
  • traced_buf_chunks_discarded:DISCARD 写满后丢掉新统计结果。

还应查看 TraceBufferV2 的 traced_buf_data_loss_* 缘由细分。这些项在 v57.2/v58.2 已存在; 是否出现及取值还取决于采集端是否上报相应统计。它们都属于 data_loss,本篇前面的General查询已覆盖,下面的 traced_buf_* 查询也会列出:

  • traced_buf_data_loss_overwrite:Ring 回卷覆盖尚Unread取的 chunk。
  • traced_buf_data_loss_smb_full:producer 上报共享内存耗尽; traced_buf_data_loss_writer_abort:writer 中止尚未完成的分片 packet。
  • traced_buf_data_loss_read_gap、traced_buf_data_loss_chunk_corrupted:读取阶段的 chunk 编号缺口或损坏。
  • traced_buf_data_loss_orphan_continuation、traced_buf_data_loss_reassembly_gap、traced_buf_data_loss_reassembly_broken_chain:缺起始片段、重组缺口或分片链断裂。

这组项按 buffer 归因,不能当作内核 per-CPU ftrace_cpu_has_data_loss 的等价替代。尤其 traced_buf_chunks_overwritten 是覆盖计数,而 traced_buf_data_loss_overwrite 表示解析器收到的具体丢GA成因; 两者都要结合目标窗口和 target_buffer 解释,不能把所有覆盖一律判为事故窗口损坏。

容量复盘要按 buffer idx 看。idx 对 traced_buf_* 通常是 buffer index,对 ftrace CPU stat 通常是 CPU id; 报告里要写清 idx_semantics,否则很容易把 CPU 3 和 buffer 3 混在一起。

1
2
3
4
5
6
7
8
9
10
11
SELECT name, idx, severity, source, value
FROM stats
WHERE value != 0
AND (
name GLOB 'traced_buf_*'
OR name IN (
'traced_buf_chunks_overwritten',
'traced_buf_chunks_discarded'
)
)
ORDER BY idx, name;

一个 central buffer 装所有数据时,高频 sched 事件可能把 process stats、log、power、FrameTimeline、App Track Event、SurfaceFlinger/Winscope 这类低频或关键数字挤出去。结果是 UI 里还能看到大量调度事件,但线程名、GF程名、内存采样、log、帧指标只剩很少一部分。

android.log 还要看设备边界。官方文档将 android.log 的兼容范围写为 userdebug; 已 root 且 logd/SELinux Scopes允许的 user 构建也可能采到日志,不能只看 build type Awarded不可用。不过 adb root 本身不保证所有设备都支持。未修改的生产 user build 上不要默认期待 android.log 数字源可用,可将外部 logcat、bugreport 或Draw台侧脱敏日志放GF同一个 case 包。

Trace configuration 文档给过一个很贴近 Android 的例子:scheduler tracing 在普通机型上可能每秒写大约 10000 个事件、约 1MB; 而内存统计 5 秒才写一次。两者放GF同一个 4MB central buffer,内存快照可能只剩一topics,甚至完全被挤掉。这种 Trace 打开后并不会报“内存采样没工作”,它只是没有留下足够证据。

短 Trace:先解决 buffer 混放

更稳的做法是把高频和低频统计结果分开:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
buffers { size_kb: 131072 fill_policy: RING_BUFFER } # 0: 高频 ftrace
buffers { size_kb: 32768 fill_policy: RING_BUFFER } # 1: 低频元数据和日志

data_sources {
config {
name: "linux.ftrace"
target_buffer: 0
ftrace_config {
ftrace_events: "sched/sched_switch"
ftrace_events: "sched/sched_waking"
}
}
}

data_sources {
config {
name: "linux.process_stats"
target_buffer: 1
process_stats_config {
scan_all_processes_on_start: true
}
}
}
This article is published by News for reference only.
1234567
Loading comments…

LinksApply

Alliance Network53