关于App UI性能的测试,Android提供了一个原生的工具Systrace,正常渲染FPS一般是在60左右,但是如果有一些代码写的不好,可能会影响到UI的性能,导致界面卡顿,这种问题是最难查的,为什么会卡顿,在哪卡顿,当然你也可以打log看时间,但是毕竟不方便。Systrace是可以解决这个问题的,我在网上查了一下关于Systrace的资料,还是比较少的,也许用的人也少吧。所以本文大部分内容翻译自谷歌官方文档
准备工作
首先如果你要运行Systrace,需要安装Python和Android SDK Tools 20 以上的版本。
同时,现在Systrace只支持Android4.1以上的版本。
开始记录
关于记录有两种方式开启,一种就是使用Python,另外一种就是使用AndroidStudio中的自带插件。
这里有一个问题,我不确认,是否使用AndroidStudio中的自带插件也需要安装Python,因为我的电脑一直安装着这些东西,所以,可以直接运行。
Python 启动
首先命令行切换到Android SDK的platform-tools下,在这个文件夹下有一个systrace文件夹,然后切到这个文件夹下:
在这个文件夹下有一个python脚本,运行即可。
python systrace.py --time=10 -o mynewtrace.html sched gfx view wm
运行规则如下:
参数名 | 意义 |
---|---|
-h,--help | 帮助信息 |
-o <FILE> | 保存的文件名 |
-t N,--time=N | 多少秒内的数据,默认为5秒,以当前时间点往后倒N个时间 |
-b N,--buf-size=N | 单位为千字节,限制数据大小 |
-k <KFUNCS> --ktrace=<KFUNCS> | 追踪特殊的方法 |
-l,--list-categories | 设置追踪的标签 |
-a <APP_NAME>,--app=<APP_NAME> | 包名 |
--from-file=<FROM_FILE> | 创建报告的来源trace文件 |
-e <DEVICE_SERIAL>,--serial=<DEVICE_SERIAL> | 设备号 |
标签简写:
简写 | 全称 |
---|---|
gfx | - Graphics |
input | - Input |
view | - View |
webview | - WebView |
wm | - Window Manager |
am | - Activity Manager |
sync | - Synchronization Manager |
audio | - Audio |
video | - Video |
camera | - Camera |
根据官方文档的意思,这些标签在SDK 17以下需要使用
--set-tags = <TAGS>
进行添加,SDK18以及更高直接用简写即可,这个标签表示生成性能分析结果中的标签,这个后面再看。
Android Studio启动
打开Android Studio:
点击如图所示的标签,打开Android Device Monitor这个界面,在左上角选择如下按钮:
然后进入可视化设置界面:
进行设置,点击ok,便可开始记录。
数据分析
我这里将会使用命令行模式进行数据记录。
在记录之前,我先写了一个简单的demo,demo有三个Activity,一个主界面,一个放有listview的Activity,一个放有RecyclerView的Activity(代码很基础我就不贴出来了)
在listview中我加入了1000个Item,每个item中都有文字和图片,RecyclerView也是。特别注意,listview没有做任何优化,因为我们要看的就是不好的效果。我先运行一下程序,然后在命令行中输入如下:
python systrace.py --time=20 -o deep.html -a deep.testsystrace sched gfx view wm
我记录了20秒内的情况,指定包名deep.testsystrace,生成文件deep.html,运行,然后不断滑动listview:
直到记录结束,命令行会有如下提示:
然后我们打开这个文件夹,找到刚才生成的deep.html。
打开这个网页:
在分析这些数据之前,我们需要先知道一些操作:
Key | Description |
---|---|
w | Zoom into the trace timeline. |
s | Zoom out of the trace timeline. |
a | Pan left on the trace timeline. |
d | Pan right on the trace timeline. |
e | Center the trace timeline on the current mouse location. |
g | Show grid at the start of the currently selected task. |
Shift+g | Show grid at the end of the currently selected task. |
Right Arrow | Select the next event on the currently selected timeline. |
Left Arrow | Select the previous event on the currently selected timeline. |
我们在网页中找到我们的工程,deep.testsystrace,但是不知道是不是bug,网页只显示了ep.testsystrace,不过根据pid也可以确认就是我们的应用。
之后我们逐个分析,首先是Frames,即帧数。我们将上图放大(快捷键w):
可以看到帧数对应的一行有许多F,各种颜色:
当显示为绿色的时候为正常,红色或者黄色分别对应的等级是e和w,也就是不正常,即达不到60fps的水准。这是我们就可以根据下面的时间分析到底是什么占用的时间了。
首先点击红色即不正常的F:
与该帧无关的操作会被置成灰色:
然后将其逐渐放大:
对比正常的帧,我们可以发现,我们obtainView和inflate调用过多。我们之前说了,listview我们没有做任何优化,每次都会重现建立view,也没有使用viewholder,所以会出现如上结果。如果我们对listview进行了优化呢?我们可以试一下,修改一下adapter的getview,当view为空时再进行创建。然后再次记录数据:
我们发现已经没有红色的F了,但是仍有少数黄色的F,我们可以根据分析再次进行优化,加上ViewHolder。这里不再做测试了。
同样我们也可以根据Alert中的提示进行修改,但是感觉提示不能直指原因,还是分析帧数,更容易找到原因。
自定义记录
我们还可以通过Trace.beginSection来记录一些信息,如下代码:
Trace.beginSection() 与 Trace.endSection() 之间代码工作会一直被追踪。结果如下,为了查看方便我把结果放大了:
可以以这种方式查看某个程序块的耗时。
总结
用这种方式可以分析出app 卡顿的一些问题的原因,从而进行解决。对于app开发人员,还是掌握较好。
更多的开发知识,可以关注我的公众号: