第三章 性能分析工具链:Perfetto、DS-5 Streamline、MTK特有的GPU调优工具
做GPU性能优化,说白了就是一场「找瓶颈」的游戏。你找不到瓶颈在哪,再牛的优化技巧也是白搭。我在MTK平台上摸爬滚打这几年,用过不下十种性能分析工具,但真正能打的核心工具,其实就这三板斧。
今天我就把这套工具链的用法和心得,掰开了揉碎了讲给你听。
3.1 Perfetto:系统级trace的瑞士军刀
Perfetto是Google主推的下一代性能追踪工具。它取代了老旧的systrace,功能强了不止一个量级。我个人习惯把它当作「第一现场勘查工具」——先跑一遍Perfetto,看看整体情况再说。
3.1.1 核心能力
Perfetto能干什么?说白了就是记录系统里「谁在什么时候干了什么」。它能看到:
- CPU每个核的调度情况
- GPU的渲染管线状态
- SurfaceFlinger的合成过程
- App的线程活动和锁竞争
- 内存分配和I/O操作
嗯,这里要注意:Perfetto的trace数据量可以非常大。我曾经在项目里开了一分钟trace,结果生成了2GB的数据文件。所以抓trace的时候,要有针对性,别一股脑全开。
3.1.2 实战用法
抓取GPU相关的trace,我一般这么配:
# 抓取GPU和显示相关的trace
adb shell perfetto \
-c - --txt \
<<EOF
buffers: {
size_kb: 524288
fill_policy: RING_BUFFER
}
data_sources: {
config {
name: "android.gpu.memory"
}
}
data_sources: {
config {
name: "android.hwcomposer"
}
}
data_sources: {
config {
name: "linux.scheduler"
}
}
duration_ms: 5000
EOF
3.1.3 怎么看GPU问题
打开Perfetto的UI界面后,我一般先看这几个关键指标:
- SurfaceFlinger的合成帧率——如果掉到30fps以下,说明合成层出问题了
- GPU渲染时长——单帧超过16ms,那就是GPU瓶颈
- CPU调度延迟——GPU在等CPU喂数据,这是常见的性能陷阱
为什么会这样?很多时候你以为GPU慢,其实是CPU没及时把数据准备好。我在一个项目中就遇到过这种情况:GPU利用率只有40%,但帧率就是上不去。一查Perfetto才发现,是CPU的渲染线程被调度到了小核上,导致数据提交延迟。
3.2 DS-5 Streamline:深入GPU内部
如果说Perfetto是「宏观侦察」,那DS-5 Streamline就是「微观解剖」。它是Arm官方提供的性能分析工具,对Mali GPU的支持尤其深入。
3.2.1 能看什么
Streamline能拿到GPU内部的硬件计数器数据,包括:
| 计数器名称 | 含义 | 正常范围 |
|---|---|---|
| GPU Fragment Active | 片元着色器活跃周期 | < 80% |
| GPU Vertex Active | 顶点着色器活跃周期 | < 60% |
| External Bus Read | 外部总线读取带宽 | 视DDR带宽而定 |
| Shader Core Utilization | 着色器核心利用率 | 30%-70% |
3.2.2 我的分析流程
拿到Streamline的数据后,我一般按这个顺序排查:
- 先看Shader Core Utilization——如果低于30%,说明GPU没吃饱,瓶颈在CPU或者带宽
- 再看External Bus Read——如果带宽打满了,那就是内存瓶颈,得考虑纹理压缩或者降低分辨率
- 最后看Fragment/Vertex Active——如果Fragment Active长期高于80%,说明片元着色器是瓶颈,得优化shader代码
我记得有一次,一个游戏场景在Mali-G52上跑不到30fps。Streamline一查,External Bus Read飙到了12GB/s,而MTK平台的DDR带宽上限也就15GB/s左右。说白了,就是纹理太大了,把带宽吃死了。后来把纹理从RGBA8888改成ETC2压缩,帧率直接翻倍。
3.3 MTK特有的GPU调优工具
MTK平台除了通用的Perfetto和Streamline,还有自己的一套工具。这些工具在座舱系统的实际调优中,往往能起到奇效。
3.3.1 MTK GPU DVFS调优
MTK的GPU有动态调频调压(DVFS)机制。但默认的DVFS策略有时候并不适合座舱场景——它更偏向省电,而不是保证流畅度。
查看当前GPU频率:
# 查看GPU当前频率
cat /proc/mali/frequency
# 查看支持的频率列表
cat /proc/mali/available_frequencies
强制锁定GPU频率(调试用):
# 锁定到最高频率
echo 800000 > /proc/mali/frequency_force
# 恢复自动调频
echo 0 > /proc/mali/frequency_force
3.3.2 MTK GPU内存调试
MTK的GPU内存管理有个特点:它会把一部分系统内存当作「伪显存」来用。如果这部分内存分配不合理,就会导致性能抖动。
查看GPU内存使用:
# 查看GPU内存分配情况
cat /d/mali/memory
# 查看GPU页表使用
cat /d/mali/pages
我曾经在调一个双屏异显的座舱项目时,发现副屏的导航地图总是卡顿。用MTK的工具一看,发现GPU给副屏分配的显存只有8MB,而导航地图的纹理缓存就需要12MB。结果就是频繁的换入换出,性能自然好不了。
解决方案是在系统属性里调大GPU的预分配内存:
# 在init.rc中增加
setprop ro.mtk.gpu.memory.reserve 64
3.3.3 MTK GPU性能计数器
MTK在/sys/class/misc/mali0/device/下暴露了很多硬件计数器,可以直接用cat命令读取:
# 查看GPU利用率
cat /sys/class/misc/mali0/device/utilization
# 查看GPU周期计数
cat /sys/class/misc/mali0/device/cycle_counter
3.4 三款工具的配合使用
这三款工具不是互相替代的关系,而是互补的。我一般的工作流是这样的:
- 先用Perfetto做全局扫描——看看是CPU瓶颈、GPU瓶颈还是I/O瓶颈
- 再用Streamline深入GPU内部——定位具体的shader或者带宽问题
- 最后用MTK工具做平台级调优——调整DVFS策略、内存分配等
举个例子,有一次座舱的仪表盘动画掉帧。Perfetto一看,GPU每帧渲染时间在18-20ms,明显超标。Streamline进一步分析,发现Fragment Active高达90%,说明片元着色器太重。最后用MTK工具把GPU频率锁定到最高,同时优化了shader里的alpha测试逻辑,终于把渲染时间压到了12ms以内。
嗯,这就是工具链的威力。没有这些工具,你就像在黑暗中摸索;有了它们,你就能精准地找到问题所在,然后一击必杀。