首页 > 技术 > 正文

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

2026-10-30  ·  阅读:440
stats / 现象影响的数据源还能回答的状况不能回答的问题处理决定
ftrace_cpu_has_data_losssched、thread_state、wakeup、Binder kernel 事件已经留下来的正向证据可以作为线索不能写“没有 Runnable 等待”“没有 wakeup 延迟”“没有调度阻塞”调度归因降级,必要时复抓
traced_buf_chunks_overwritten / discarded命中同一个 buffer 的数据源未被覆盖窗口里的正向证据被覆盖窗口里的 App marker、FrameTimeline、process/thread metadata按 idx 找 buffer 和 target_buffer,决定复抓或降级
FrameTimeline 表有行但方向窗口覆盖不完整FrameTimeline可说明残留帧事实不能证明方向窗口帧指标完整输出 frame_metrics_partial
clock_sync_failure*时间戳转换部分非时段类元数字不能做精确时序、duration、跨线程排序先按时间语义不可信处理
perf_* / heapprofd_* / meminfo_* / rss_stat_*CPU profiling、native allocation、RSS/PSS、系统内存依赖未受影响的统计结果源的结论对应 profile 或内存口径指标级降级

报告字段也要固定,否则每次还是靠人写判断:

1
2
trace_quality_status,affected_sources,affected_metrics,usable_metrics,unusable_metrics,evidence_grade,fallback_used,recapture_required,recapture_reason,next_trace_config_change
partial,ftrace;sched,Runnable;wakeup,FrameTimeline;AppTrackEvent,RunnableNegativeConclusion,weak,false,true,ftrace_cpu_has_data_loss,reduce_ftrace_events+increase_ftrace_buffer

如果要专门排查 buffer 压力,可以再按 buffer 维度看覆盖和丢弃。有些版本里这些计数会被归类为 info,只按 data_loss 过滤会漏掉线索:

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

如果要确认帧指标能不能用,再查 FrameTimeline。它不是 ftrace 的直接产物,但也会受 data source 是否启用、Android 版本、central buffer 覆盖和 parser/pairing 异常冲击:

1
2
3
4
5
SELECT 'actual' AS table_name, COUNT(*) AS row_count
FROM actual_frame_timeline_slice
UNION ALL
SELECT 'expected' AS table_name, COUNT(*) AS row_count
FROM expected_frame_timeline_slice;

只查全表行数还不够。帧记录本来就不是连续信号,静止页面可能没有新帧;min/max 包住窗口既不能证明中间无丢帧记录,也不是完整采集的必要条件。应按方向 upid、layer、frame token 核对 expected/actual 配对、未闭合或 dropped frame、采集启停和同源 buffer loss。下面只列出窗口内已观测帧的范围,不能据此自动判定完整。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
INCLUDE PERFETTO MODULE time.conversion;

WITH target_window(start_ts, end_ts) AS (
VALUES (123000000000, 123500000000)
)
SELECT
'actual' AS table_name,
COUNT(*) AS row_count,
time_to_ms(MIN(a.ts)) AS min_ts_ms,
time_to_ms(MAX(a.ts + a.dur)) AS max_end_ms
FROM actual_frame_timeline_slice a
JOIN target_window w
WHERE a.ts < w.end_ts
AND a.ts + a.dur > w.start_ts
UNION ALL
SELECT
'expected' AS table_name,
COUNT(*) AS row_count,
time_to_ms(MIN(e.ts)) AS min_ts_ms,
time_to_ms(MAX(e.ts + e.dur)) AS max_end_ms
FROM expected_frame_timeline_slice e
JOIN target_window w
WHERE e.ts < w.end_ts
AND e.ts + e.dur > w.start_ts;

如果要做更宽的采集配置复盘,可以再看所有非零统计项:

1
2
3
4
5
6
7
8
9
SELECT name, idx, severity, source, value
FROM stats
WHERE value != 0
ORDER BY CASE severity
WHEN 'data_loss' THEN 0
WHEN 'error' THEN 1
WHEN 'notice' THEN 2
ELSE 3
END, name, idx;

source 也要看。source = 'trace' 通常指采集或 trace 资讯本身的状况,优先回到 TraceConfig、producer 或设备能力;source = 'analysis' 更偏 Trace Processor 导入、解析、建模阶段,优先看导入参数、解析器版本、producer 写法或 trace 格式问题。看到 parser error 时,不要默认只靠加 buffer 解决。

stats 的读法不要停在“有没有值”。读到非零项后,还要接着追问:

本文由News整理发布,仅供参考。

1234567
评论加载中…

友情链接申请友链

联盟矩阵53