目录:
本篇文章通过介绍 linux.sys_stats 数据源,来看perfetto怎么添加数据源。
这应该是唯一写这方面东西的文章,当时为了搞这个功能100多个英文文档全浏览了一遍,可惜官网文档没写,接着又撸源码,搞了一周多。
前言
新增 perfetto 数据源
-
新增 ftrace 事件看这里的文档 perfetto.dev/docs/contri…
-
新增 atrace 看atrace相关代码即可,很多人都知道,也有很多文档介绍。
-
对 /proc 和 /sys 等这种perfetto相对ftrace、atrace特有的数据源该怎么添加??
perfetto 对于 进程状态,内存状态,GPU\CDSP\ddr\ufs频点信息 这些数据,是通过 traced_probes 轮询 /proc 和 /sys 等内核接口轮询得到的。
通过分析 inux.sys_stats 这个数据源,可以看到 perfetto 怎么新增数据源的。
一个 linux.sys_stats 数据源的配置示例:
buffers: {
size_kb: 63488
fill_policy: DISCARD
}
data_sources: {
config {
name: "linux.sys_stats"
sys_stats_config {
devfreq_period_ms: 1000
}
}
}
duration_ms: 15000
devfreq_period_ms
看下文档 perfetto.dev/docs/refere… 说明
| Field | Type | Description |
|---|---|---|
| devfreq_period_ms | uint32 | Polls /sys/devfreq/*/curfreq every X ms, if non-zero. This is required to be > 10ms to avoid excessive CPU usage. This option can be used to record unchanging values. Updates from frequency changes can come from ftrace/set_clock_rate. |
devfreq_period_ms 配置大于0的值后,轮询 /sys/class/devfreq/*/cur_freq 的值,并记录在 trace buffer 中
/sys/class/devfreq/*/cur_freq 的内容是什么?
是各种器件的频率,CPU0~CPU7的频率,ufs,ddr,GPU等等。
也就是说对于上面例子中的数据源配置 devfreq_period_ms,表示持续跟踪 设备中CPU0~CPU7的频率,ufs,ddr,GPU等的频率。
那么我们现在要新增一个数据,比如GPU的使用百分比,perfetto的代码中改怎么修改?
这个过程远没有想的那么简单。
已知 /sys/class/xxxx/xxxx/gpu_busy_percentage 节点表示GPU的百分比,下面手把手的讲述怎么让 perfetto 持续跟踪这个节点的数据,并在UI界面上显示出来。
正文
一、定义新的配置属性 gpu_period_ms:
新增配置属性 gpu_period_ms,配置写法如下:
cat <<EOF > /data/misc/perfetto-configs/sys_stats && perfetto --txt -o /data/misc/perfetto-traces/trace -c /data/misc/perfetto-configs/sys_stats
buffers: {
size_kb: 63488
fill_policy: DISCARD
}
data_sources: {
config {
name: "linux.sys_stats"
sys_stats_config {
devfreq_period_ms: 1000 // 这个 devfreq_period_ms 也带上,作为对比
gpu_period_ms: 1000// 这个gpu_period_ms用于表示跟踪 /sys/class/xxxx/xxxx/gpu_busy_percentage 的数据
}
}
}
duration_ms: 15000
二、对于代码的修改围绕以下四个问题
1. 定义要抓什么数据
2. 定义数据要怎么记录存储
3. 数据怎么抓
4. 数据怎么解析
一、通过.proto文件,定义”抓什么数据“以及”数据怎么记录存储“
- /external/perfetto/protos/perfetto/config 目录定义了抓什么数据
- /external/perfetto/protos/perfetto/trace 目录定义了数据怎么记录存储
1、修改 /external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.proto
- 新增配置项 gpu_period_ms
- 这个配置文件用于 /system/bin/traced_probes
- traced_probes 根据是否有传入的这个参数确定是否轮询 /sys/class/kgsl/kgsl-3d0/gpu_busy_percentage 节点,并记录进trace文件
- 这部分代码”定义了抓什么数据“修改代码如下:
- 这部分修改将编译到so库: system/lib64/libperfetto.so
2、修改 /external/perfetto/protos/perfetto/trace/sys_stats/sys_stats.proto
-
这部分代码用于”定义数据怎么记录存储“,用于 protobuf 序列化数据为 .proto 2进制数据。
-
新增trace数据对象,修改代码如下:
- 编译到so库: system/lib64/libperfetto.so
3、执行命令:tools/gen_merged_protos
-
这个命令会把所有的 配置文件 和 所有的 trace数据对象 文件分别合并到两个文件中:
- protos/perfetto/config/perfetto_config.proto
- protos/perfetto/trace/perfetto_trace.proto
- 命令执行完后,对 sys_stats_config.proto、sys_stats.proto 的修改会merge到这两个文件中。
- 这两个文件用于 用于 /system/bin/perfetto 的 --txt 参数。
- 没有这个修改,perfetto 不识别新增的配置。
二、修改怎么抓trace的代码
配置文件告诉了要抓什么数据,以及数据改怎么记录
至于怎么抓trace。需要写代码去实现
- 代码实现 src/traced/probes/sys_stats/sys_stats_data_source.cc
- 代码编译到so库: system/lib64/libperfetto.so
写代码的话,需要了解 protobuf 原理。重点要了解 .proto 文件编译生成什么样的源码
protobuf 原理非常简单的简述:
- 把 .proto 文件编译为java、c++、go、python等目标语言
- 这个编译过程类似JavaBean,Android 的序列化对象 Parcelable。会生成getter、setter等等方法
三、修改怎么解析trace的代码
trace抓到了,但是数据怎么解析,也需要我们自己写代码处理
- 数据解析代码在 src/trace_processor 目录下
- 数据解析的理论知识参见:perfetto.dev/docs/analys…
- 解析器会编译成各种各样的格式
- 解析trace数据,形成数据库,并暴露SQL查询接口
- 解释消息事件,根据数据生成用户友好的描述信息
- chrome 使用 trace_processor 作为WebAssembly 的模块,从编译过程看应该叫 trace_processor_wasm
- 对于 SysStats 数据,trace_processor 会根据原始的trace数据生成 Events、Counters、Tracks 等等信息
- 浏览器根据这些信息生成UI界面
1、修改 src/trace_processor/importers/proto/system_probes_parser.cc
2、编译 浏览器UI界面
- 内容太多见 ”perfetto高阶使用:编译浏览器UI“ 文章
附:
编译
-
编译 浏览器UI
- 新增的配置,使用ui.perfetto.dev/ 无法解析。需要编译自己的 浏览器UI
-
编译 libperfetto.so
- sys_stats 数据源处理代码sys_stats/sys_stats_data_source.cc会编译到 libperfetto.so
- sys_stats_config.proto 和 sys_stats.proto 生成的c++代码会被 sys_stats/sys_stats_data_source.cc调用
- 因此对这两个 proto 文件的修改也需要重新编译 libperfetto.so
-
编译 perfetto 命令行客户端
- 对 sys_stats_config.proto 和 sys_stats.proto 两个配置文件修改需要编译命令行客户端工具 perfetto
- 主要用于解析 --txt 参数的配置文件
- /external/perfetto/protos/perfetto/config/perfetto_config.proto
- /external/perfetto/protos/perfetto/trace/perfetto_trace.proto
- 主要用于解析 --txt 参数的配置文件
- 对 sys_stats_config.proto 和 sys_stats.proto 两个配置文件修改需要编译命令行客户端工具 perfetto
## 编译命令
prebuilts/build-tools/linux-x86/bin/ninja -j32 -f out/combined-xxxx.ninja libperfetto.so perfetto -j32
## 不用编译 traced 和 traced_probes
## sys_stats 的数据源在 traced_probes 进程中
## 但是相关源码编译到了共享库 libperfetto.so 中,bin程序文件使用 libperfetto.so。因此编译 libperfetto.so 即可
## 需要push到 system/lib64/libperfetto.so , 不用push到system/lib, 这个目录下没有
后记综述
-
perfetto 从配置文件上看,各个模块是高度耦合的。是个非常劣势的特点
-
配置文件的修改后,需要同步更新 命令行客户端,UI浏览器工具,抓trace的进程都需要更新相应的程序文件。
对于 linux.sys_stats 的数据源,需要更新以下程序文件:
- 手机上system/lib64/libperfetto.so。/system/bin/traced_probes 会用到,用于抓 Ftrace, /proc, /sys 等数据
- 手机上bin文件 perfetto(命令行客户端)
- 桌面端浏览器UI:UI服务器程序
- 其他不重要的程序:trigger_perfetto、trace_processor_shell 等等
-
这个可以理解的。因为使用的 protobuf,这个的目标就是高性能,低存储。主要是极低的存储。
- protobuf 可以看作极致压缩的json。
- 把每种字段,变量,信息,消息等等,都使用一个数值映射,这种替代,对内存和存储进行了极致的压缩。
- 解析端,依赖 配置文件正确的解析数据
- perfetto 需要对传入的纯文本配置文件,转为 protobuf 二进制数据
- 真正干活的 traced_probes 进程依赖配置文件做具体的操作
- 这个就导致,配置文件变更,各方面的程序都要更新
- protobuf 可以看作极致压缩的json。
-
综上,新增一个配置项,是个复杂的工程!!!