2、定位工具入门:Profile GPU Rendering与开发者选项的妙用
说到卡顿定位,很多新手第一反应就是「看Logcat」。嗯,Logcat确实能看报错,但卡顿这种性能问题,它往往一声不吭。真正好用的工具,其实就藏在开发者选项里。
我个人习惯,拿到一台测试机,第一件事就是打开开发者选项。不是去开什么USB调试,而是先把「Profile GPU Rendering」和「GPU呈现模式分析」这两个开关摸清楚。说白了,它们就是卡顿的「照妖镜」。
2.1 开发者选项:你的性能工具箱
开发者选项里东西很多,但跟卡顿定位相关的,我重点说几个。
| 功能名称 | 作用 | 我的使用频率 |
|---|---|---|
| GPU呈现模式分析 | 以柱状图显示每帧的渲染耗时 | ★★★★★ |
| Profile GPU Rendering | adb命令版,更精确的数据输出 | ★★★★☆ |
| 严格模式 | 检测主线程的长时间操作 | ★★★☆☆ |
| 显示刷新率 | 实时显示当前屏幕刷新帧率 | ★★★☆☆ |
| 动画缩放 | 调整窗口动画速度,辅助观察 | ★★☆☆☆ |
你想想看,如果连帧率都看不到,你怎么判断卡没卡?所以「显示刷新率」是我必开的。它会在屏幕左上角显示一个实时数字,60fps就是流畅,掉到30以下,那肯定卡了。
2.2 GPU呈现模式分析:柱状图里看门道
这个功能在开发者选项里叫「GPU呈现模式分析」,选「在屏幕上显示为条形图」。开启后,屏幕底部会出现一排彩色竖条。
每个竖条代表一帧。竖条越高,渲染耗时越长。绿色横线是16ms的基准线——超过它,就意味着掉帧。
关键点:竖条的颜色代表不同阶段:
- 蓝色:测量与布局(onMeasure、onLayout)
- 红色:绘制(onDraw)
- 橙色:CPU等待GPU的时间
- 绿色:GPU处理时间
我在项目中遇到过一个问题:列表滑动时偶尔卡顿,看柱状图发现蓝色条特别高。嗯,这说明布局测量耗时太长。后来一查,是某个Item的嵌套层级太深,RelativeLayout套了三层。改成ConstraintLayout后,蓝色条直接降了一半。
我的小技巧:如果红色条高,说明onDraw里画了太多东西。比如自定义View里用了大量Path或Bitmap绘制。这时候就该考虑缓存或简化绘制逻辑了。
2.3 Profile GPU Rendering:更精确的adb命令
屏幕上的柱状图虽然直观,但精度有限。如果你想拿到精确的每帧耗时数据,就得用adb命令。
adb shell dumpsys gfxinfo <包名>
这个命令会输出当前应用每一帧的详细数据,包括:
- Draw:绘制耗时
- Prepare:准备耗时
- Process:处理耗时
- Execute:执行耗时
我个人习惯把它重定向到文件里分析:
adb shell dumpsys gfxinfo com.example.app > gfxinfo.txt
然后看最后面的「HISTORY」部分,它会列出最近128帧的详细数据。如果发现连续多帧超过16ms,那基本可以确定有性能瓶颈。
注意:这个命令需要应用处于调试模式,或者系统是userdebug版本。否则可能拿不到数据。我曾经在正式版手机上折腾了半天,最后才发现是权限问题。
2.4 严格模式:抓主线程的「小偷」
有时候卡顿不是渲染问题,而是主线程干了不该干的事。比如网络请求、文件读写、大循环计算。这时候「严格模式」就派上用场了。
开启方式很简单:
// 在Application或Activity的onCreate中开启
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads() // 检测磁盘读
.detectDiskWrites() // 检测磁盘写
.detectNetwork() // 检测网络操作
.penaltyLog() // 输出日志
.penaltyFlashScreen() // 屏幕闪烁提醒
.build());
开启后,一旦主线程做了违规操作,Logcat会打印警告,屏幕边缘还会闪烁一下。我曾经在一个老项目里开启严格模式,结果屏幕闪得跟迪斯科一样——好家伙,一个列表加载时居然在主线程里读写SharedPreferences。
建议:严格模式只在开发阶段开启。发布版本一定要关掉,否则会影响性能。我一般会在BuildConfig.DEBUG条件下开启。
2.5 实战:三步定位一个卡顿问题
说了这么多工具,咱们来走一遍实战流程。假设你发现某个页面滑动卡顿:
- 第一步:看帧率。打开「显示刷新率」,确认帧率是否稳定在60fps。如果频繁掉到30以下,继续下一步。
- 第二步:看柱状图。打开「GPU呈现模式分析」,观察竖条颜色。蓝色高→布局问题;红色高→绘制问题;橙色高→CPU等待GPU。
- 第三步:拿精确数据。用adb命令导出gfxinfo,找到耗时最高的帧,分析具体是哪个阶段超时。
举个例子,我上次遇到一个相册滑动卡顿。第一步发现帧率在20-30之间跳。第二步看到蓝色条特别高。第三步导出数据,发现Prepare阶段耗时超过50ms。最后定位到是每个图片Item在加载时都重新解析了Bitmap,改成复用后问题解决。
2.6 避坑指南
最后说几个我踩过的坑:
- 别在模拟器上测。模拟器的GPU渲染和真机差异很大,柱状图数据不准。我建议直接用真机。
- 注意系统版本差异。Android 6.0和10.0的Profile GPU Rendering输出格式不一样。老版本的数据字段名可能不同。
- 别只看平均值。卡顿往往是偶发的,平均值可能很好看。要看最大值和连续掉帧的帧数。
- 关闭省电模式。省电模式会限制CPU/GPU频率,导致渲染变慢。测试时一定要关掉。
嗯,工具就这些。说白了,Profile GPU Rendering和开发者选项就是你的「听诊器」和「血压计」。用好了,卡顿问题基本能定位个七七八八。下一章咱们聊聊更高级的工具——Systrace,那才是真正的「CT机」。