【Perfetto从入门到精通】5. Perfetto Data Source(数据源)简介

283 阅读8分钟

要爱生活,胜过爱生活的意义。要爱具体的人,而不是抽象的人类。——《卡拉马佐夫兄弟》

Perfetto是围绕着 数据驱动 而建设的性能分析工具,在这套工具体系中,数据源(Data Source)是一个重要的概念,它是系统中各项性能指标的量化表达。

使用 perfetto --query 查看 Android 设备支持的数据源

不同的手机系统,能够支持的数据源类型和数量都有所区别,这会直接决定到我们进行性能分析的可行性。 如果手机系统不支持某些数据源,就无法抓取到对应的性能指标数据。

通过命令 adb shell perfetto --query 可以查看当前设备所支持的数据源(破折号——后的部分为笔者注释):

λ adb shell perfetto --query
Not meant for machine consumption. Use --query-raw for scripts.

Service: Perfetto v49.0 (N/A) —— 设备上运行的 Perfetto 版本
Tracing sessions: 0 (started: 0) —— 当前在执行的 Tracing 任务数量


PRODUCER PROCESSES CONNECTED: —— 已连接到 Perfetto Service 的数据生产者列表

ID     PID      UID      FLAGS  NAME                                       SDK
==     ===      ===      =====  ====                                       ===
1      2466     9999            traced
2      2462     9999            perfetto.traced_probes                     Perfetto v49.0 (N/A)
3      2134     1072            /system/bin/gpuservice                     Perfetto v49.0 (N/A)
4      2163     1000            /system/bin/surfaceflinger                 Perfetto v49.0 (N/A)
5      3010     1000            system_server                              Perfetto v49.0 (N/A)
6      994      1000            /system/bin/servicemanager                 Perfetto v49.0 (N/A)
7      4483     10079           com.android.systemui                       Perfetto v49.0 (N/A)
8      4937     1000            /** 略 **/                		           Perfetto v49.0 (N/A)
9      5097     10103           /** 略 **/		                           Perfetto v49.0 (N/A)
10     5072     1002            com.android.bluetooth                      Perfetto v49.0 (N/A)
/** 下略 **/


DATA SOURCES REGISTERED: —— 数据生产者对外暴露的数据源,一个生产者可以生产多种类型数据源

NAME                                     PRODUCER                     DETAILS
===                                      ========                     ========
android.bluetooth_tracing                com.android.bluetooth (10)
android.game_interventions               perfetto.traced_probes (2)
android.gpu.memory                       /system/bin/gpuservice (3)
android.heapprofd                        traced (1)
android.inputmethod                      system_server (5)
android.inputmethod                      com.android.systemui (7)、
android.java_hprof                       traced (1)
android.java_hprof.oom                   traced (1)
android.kernel_wakelocks                 perfetto.traced_probes (2)
android.log                              perfetto.traced_probes (2)
android.packages_list                    perfetto.traced_probes (2)
android.polled_state                     perfetto.traced_probes (2)
android.power                            perfetto.traced_probes (2)
android.protolog                         system_server (5)
android.protolog                         com.android.systemui (7)
android.sdk_sysprop_guard                traced (1)
android.statsd                           perfetto.traced_probes (2)
android.surfaceflinger.frame             /system/bin/surfaceflinger (4)
android.surfaceflinger.frametimeline     /system/bin/surfaceflinger (4)
android.surfaceflinger.layers            /system/bin/surfaceflinger (4)
android.system_property                  perfetto.traced_probes (2)
com.android.wm.shell.transition          system_server (5)
com.android.wm.shell.transition          com.android.systemui (7)
linux.ftrace                             perfetto.traced_probes (2)   gfx,input,view,webview,wm,am,sm,audio,vi... (use --long to expand)
linux.inode_file_map                     perfetto.traced_probes (2)
linux.perf                               traced (1)
linux.process_stats                      perfetto.traced_probes (2)
linux.sys_stats                          perfetto.traced_probes (2)
linux.sysfs_power                        perfetto.traced_probes (2)
linux.system_info                        perfetto.traced_probes (2)
perfetto.metatrace                       traced (1)
perfetto.metatrace                       perfetto.traced_probes (2)
track_event                              system_server (5)            always,gfx,input,view,webview,wm,am,sm,a... (use --long to expand)
track_event                              /system/bin/servicemanager (6) servicemanager
track_event                              com.android.systemui (7)     always,gfx,input,view,webview,wm,am,sm,a... (use --long to expand)
track_event                              /system/bin/surfaceflinger (12) always,gfx,input,view,webview,wm,am,sm,a... (use --long to expand)


TRACING SESSIONS: —— 当前正在执行的 Tracing 任务细节

ID      UID     STATE      BUF (#) KB   DUR (s)   #DS  STARTED  NAME
===     ===     =====      ==========   =======   ===  =======  ====

系统中存在10+的数据生产者以及20+数据源类型,我们不必对每一种数据源都了然于心。下文将对那些可以帮助我们分析性能的主要数据源进行讲解和介绍。在学习数据源之前,先了解一下Perfetto进行数据采集的架构模型。

Perfetto 数据收集 CS 架构

producer-service-consumer.png

Perfetto 采用 Client-Service 的 CS 架构。如上图所示,位于系统中心的Tracing service 相当于数据的中转站,在上游接收 Producer 传来的各项原始数据,将这些原始数据保存在 Tracing service 内部的 buffer 缓冲区中,并通过 IPC 调用,进一步将数据交给下游的消费者。

我们启动Perfetto数据采集时,不论是通过网站(ui.perfetto.dev/) 还是命令行工具(cat config.pbtx | adb shell perfetto -c - --txt -o /data/misc/perfetto-traces/trace.pftrace),都相当于创建了一个 数据消费者,将其挂载到 Tracing service 上,从而建立对数据生产者的监听。

生产者:Producer

每个Producer = 一类能力的来源

  • traced:Java heap、heapprofd、linux.perf、metatrace 等
  • traced_probes:ftrace / tracefs / CPU scheduling / binder / irq
  • surfaceflinger:帧时间、FrameTimeline
  • gpuservice:GPU相关数据

Producer描述了设备本身的能力,这些能力所收集到的数据,以 Data Source 形式呈现给开发者,只有在列表里的 Data Source,才能够在客户端 config 里进行设置,从而采集该数据。

笔者遇到过设备不支持 linux.ftrace 的场景,无论怎么设置 config,都无法获取到 CPU 任务调度轨道(CPU Scheduling)。

在已经具备 root 权限的前提下,执行 adb shell setprop ctl.start traced_probes 可以开启 traced_probes 生产者,从而采集 linux.ftrace

分析对象与常见数据源的对应关系

分析对象数据源描述什么信息解决什么问题
一、CPU & 线程linux.perfCPU Profiling,火焰图
谁在占用CPU,热点函数定位,调用链
卡顿,掉帧
异常耗电,CPU飙高
linux.ftraceCPU调度信息(谁唤醒了谁等)sched_switch / sched_waking / sched_wakeupCPU被抢占,线程得不到运行
linux.process_stats进程名,线程名,PID,TIDPerfetto UI 显示不出进程名
二、UI & 卡顿android.surfaceflinger.frametimeline帧序列,是否发生掉帧,掉帧发生在App/SF/GPU哪一步UI 掉帧卡顿
android.surfaceflinger.frame
android.surfaceflinger.layers
UI 结构信息,帧提交,Layer变化UI 掉帧卡顿
三、内存android.heapprofdNative / Java 堆哪些对象占内存,是否有泄露趋势
android.java_hprofJava Heap Dump 内存快照内存泄漏分析
四、系统负载 & 背景环境linux.sys_statsCPU使用率,内存信息,上下文切换数量给 perf / ftrace 提供背景信息
android.power / linux.sysfs_powerCPU频率变化,电源状态同样的代码,执行起来时快时慢
五、日志 & 事件android.log
trace_event
logcat 输出将关键日志与性能时间线对齐

Q:为什么不同的 PRODUCER 可以对应相同的 NAME ?

例如下面这段,一个 android.inputmethod 数据源,居然有8个不同的生产者,要如何理解?难道不是一个数据源只能由一个生产者提供么?

android.inputmethod system_server (5)
android.inputmethod com.android.systemui (7)
android.inputmethod com.vivo.upslide (8)
android.inputmethod com.bbk.launcher2 (9)
android.inputmethod com.vivo.globalanimation:drawing (11)
android.inputmethod com.vivo.ai.ime.nex (13)
android.inputmethod com.vivo.hiboard (14)
android.inputmethod com.vivo.globalsearch (15)

A: NAME 不是“全局唯一的数据源”,而是“同一种接口/协议的数据源实例”

同一个 NAME 可以被多个 Producer 同时提供,这是 Perfetto 的设计特性。

Perfetto 的真实模型是:

一个 NAME = 一种“数据源类型 / 接口协议”
多个 Producer = 各自提供这个接口的一个实例

对于上述 android.inputmethod 的例子,其数据生产者都“实现/接入”了该数据源接口,它们提供各自进程内的 input 相关事件,并非是共享的同一份数据。

Perfetto 进行这种设计,遵循的原则是“谁产生事件,谁就自己上报”。好处有以下几点:

  • 无跨进程侵入
  • 权限边界清晰
  • 开销可控
  • App/组件可以按需接入

如果我们想对数据源 android.inputmethod 进行收集,则需要在配置文件里写:

data_sources {
  config {
    name: "android.inputmethod"
  }
}

这样会对 所有 注册了 android.inputmethod 的 Producer 都启用该数据源。最终在 trace 里,数据仍然按照 进程/线程 分轨道显示。

当然,系统中也存在一些唯一的数据源 NAME,它们有且仅有唯一的 PRODUCER。

  • linux.perf → 只有 traced
  • linux.ftrace → 只有 perfetto.traced_probes
  • android.heapprofd → 只有 traced

它们共同的特点是:

系统级、集中式、跨进程视角

中转站:Service

image.png

Tracing service 是位于 Producer 和 Consumer 之间,承上启下的桥梁。它读取 Consumer 所设置的配置信息,维护相应 buffer,并按照配置中的数据源,从 Producer 中采集数据。它具有如下职责:

  • 维护一个生产者-数据源对应关系的注册表。
  • 管理数据缓冲区。
  • 处理多个 Tracing Session 并行收集的场景。
  • 将 Consumer 提供的配置给到对应的 Producer。
  • 告知 Producer 进行 Tracing 的时机和内容。
  • 将数据从 Producer 的共享内存缓冲区移动到自身的非共享内存缓冲区。
  • 最终通过写文件的方式,将采集到的数据进行持久化。

消费者:Consumer

消费者是数据的应用方,它可以表现为多种可信实体(Linux/Android 上的命令行客户端,Chrome 中的浏览器进程接口)。它可以与 Tracing Service 进行 IPC 通信并读取其缓冲区。

对这两种操作的详细描述如下:

  • 向 Tracing service 发送跟踪配置,确定:
    • 要创建的 Tracing buffer 数量。
    • Tracing buffer 的大小。
    • 每个 Tracing buffer 的策略(Stop when full, Ring buffer, Long trace)。
    • 要启用的数据源。
    • 每个数据源的配置。
    • 每个已配置数据源生成的数据的目标 Buffer。
    • 启用和禁用 Tracing。
  • 读取跟踪缓冲区:
    • 通过 IPC 通道流式传输数据。
    • 向 Tracing service 传递文件描述符,并指示其定期将 Tracing buffer 保存到文件中,即 perfetto -o 参数指定的文件如 /data/misc/perfetto-traces/trace.pftrace

用一张图描述 Producer/Service/Consumer

perfetto_arch.png

附:常见 Android 性能问题 → Perfetto 数据源对照表

性能问题 / 现象首选数据源重点看什么常见结论 / 行动
CPU 占用高 / 手机发热linux.perf
linux.process_stats
火焰图热点函数、线程归属热点在业务函数→优化算法/频率;热点在框架/IO→检查调用频次
偶发卡顿(非 UI)linux.perf
linux.ftrace
linux.process_stats
热点是否伴随频繁切换/唤醒不是“慢”,而是被打断→减少锁/跨线程唤醒
UI 掉帧 / 丝滑度差android.surfaceflinger.frametimeline
linux.ftrace
linux.process_stats
哪一段掉帧(App/SF/GPU)App 段慢→主线程;SF/GPU→过度绘制/纹理
主线程阻塞linux.perf
android.surfaceflinger.frametimeline
主线程火焰图、帧时间同步 IO/大对象/反射→移到后台
线程频繁被切走linux.ftrace (sched_switch)同一线程短时间多次切换优先级不当/CPU 竞争→调度/合并任务
频繁唤醒导致抖动linux.ftrace (sched_waking)谁在唤醒谁、频率锁/条件变量/Binder 风暴→合并唤醒
Binder 相关卡顿linux.ftrace
linux.perf
唤醒链 + Binder 栈同步 Binder/大包→异步/拆包
后台任务拖慢前台linux.perf
linux.ftrace
前后台线程竞争后台降频/限速/WorkManager 约束
启动慢(冷/温)linux.perf
android.surfaceflinger.frametimeline
启动阶段热点、首帧初始化过多→延迟加载
耗电异常(CPU)linux.perf
linux.sys_stats
android.power
长时热点 + 频率忙等/轮询→事件驱动
同样代码时快时慢linux.sys_stats
android.power
linux.perf
频率/负载背景DVFS/负载干扰→降频敏感点
内存抖动/泄漏android.heapprofd
android.java_hprof
分配热点/存活对象对象复用/生命周期修正
日志影响性能android.log
linux.perf
日志与卡顿对齐关键路径禁用/降级日志
不明原因卡顿linux.perf
linux.ftrace (sched_switch, sched_waking)
linux.process_stats
android.surfaceflinger.frametimeline
linux.sys_stats
多源对齐先定性再定量

参考资料