Profile GPU rendering
开发者选项--Profile GPU Rendering(GPU呈现模式分析),参见下图。
如上图所示,打开之后就会显示出柱状图,柱状图有四种颜色
- 红 :代表执行的时间,这部分是Android进行2D渲染Display List的时间,为了绘制到屏幕上,Android需要使用OpenGl ES的API接口来绘制Display List,这些API有效地将数据发送到GPU,最终在屏幕上显示出来。当红色的线非常高时,可能是由重新提交了视图而导致的
- 黄:表示处理时间,或者是CPU告诉GPU渲染一帧的地方,这是一个阻塞调用,因为CPU会一直等待GPU发出接到命令的回复,如果柱状图很高,就意味着GPU太繁忙了
- 蓝 :代表测量绘制的时间,它代表需要多长时间去创建和更新DisplayList。在Android中,一个视图在进行渲染之前,它必须被转换成GPU熟悉的格式,简单来说就是几条绘图命令,蓝色就是记录了在屏幕上更新视图需要花费的时间,也可以理解为执行每一个View的onDraw方法,创建或者更新每一个View的Display List对象。在蓝色的线很高时,有可能是因为需要重新绘制,或者自定义视图的onDraw函数处理事情太多。
- 紫(绿):表示将资源转移到渲染线程的时间,只有Android 4.0及以上版本才会提供。
任何时候超过警戒线(警戒线,对应时长16ms),就有可能丢失一帧的内容,虽然对于大部分应用来说,丢失几帧确实感觉不出卡顿,但保持UI流畅的关键就在于让这些垂直的柱状条尽可能地保持在警戒线下面。
这里可以通过:adb shell dumpsys gfxinfocom..(包名)把具体的耗时输出到日志中来分析。
整体感觉这个用途不是特别大,就简单看下稳定后的运行情况尚可,一般页面刚进入的时候都比较高,稳定后值相对比较均衡。能够简单的分析一些页面情况,具体分析还得靠下面更细致的工具,比如说TraceView
TraceView
TraceView是AndroidSDK自带的工具,用来分析函数调用过程,可以对Android的应用程序以及Framework层的代码进行性能分析。它是一个图形化的工具,最终会产生一个图表,用于对性能分析进行说明,可以分析到应用具体每一个方法的执行时间,使用可以非常直观简单,分析性能问题很方便。
方法1:代码埋点
//开始埋点,“app”是最后生成的性能分析文件
Debug.startMethodTracing("block_test");
/**------------->>>>这里是你要监控的代码<<<<<------------------------------*/
//埋点结束,期间start 到 stop 之间的代码,就是你要测试的代码范围
Debug.stopMethodTracing();
这种适合已经大概知道什么代码块有卡顿,用于协助分析,比如点击某个按钮的代码块。
示例代码:
@Override
public void onClick(View v) {
//开始埋点,“block_test”是最后生成的性能分析文件
Debug.startMethodTracing("block_test");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//埋点结束,期间start 到 stop 之间的代码,就是你要测试的代码范围
Debug.stopMethodTracing();
}
触发之后就会在如下目录生成对应trace文件
注意路径是sdcard下面这个
/sdcard/Android/data/com.canzhang.sample/files/block_test.trace
直接双击就可以自动使用 android studio 打开此文件
部分1:是时间选择范围,整段就是我们刚刚用代码埋点指定的。上面的时间标志是时间戳。
部分2:表示当前埋点的代码有5个线程。可以点击任何一个线程查看
部分3:这里有4个按钮
- Call Chart
- Flame Chart
- Top Down
- Bottom Up
Top Down
首先是箭头1指示的标题栏有几个关键字段释义
- Total:表示main函数所有执行需要的时间
- Self: 表示main函数里,除了调用别的函数方法外,自己方法内代码的执行时间
- Children: 表示mian函数里,调用别的函数所执行的时间
然后是箭头2指示的有个下拉选择窗,有以下选项
- Wall Clock Time:指这个线程真正的执行时间,比如消耗了100ms就是消耗了100ms
- Thread Time:CPU的执行时间,比Wall Clock Time少。
为什么这两个时间会不一样?举个不恰当的比喻,比如运行一个方法,因为锁的原因,线程等待。这个时候等待时间也算在了Wall Clock Time里。 但是Thread Time是CPU的执行时间,线程闲置的时候并没有消耗CPU,当然这个等待时间也就不算在Thread Time里了。
最后是箭头3
表示方法的依次调用。及每个子方法调用所消耗的时间。这里也可以看成是Call Chart表的“代码化”。
其实从这里就可以直观的看出是点击比较耗时,我们继续展开就可以看到具体是sleep比较耗时,耗时刚好是5s左右。
这里我们还可以切成Thread Time
模式,这个是cpu执行时间,而我们调用的是线程的sleep方法,不会占用cpu时间,所以时间会少很多,如下图所示(单位微秒):
Call Chart
也是一个方法的调用栈
- 橙色:表示系统API方法调用
- 绿色:表示自身方法调用
- 蓝色:表示第三方调用
Flame Chart
和上面的差不多,也是方法调用统计
Bottom Up
统计谁调用了谁,比如这里点开sleep,发现是onClick调用的
上面是通过代码的方式调用的,我们还可以通过其他方式IDE的一些按钮应用
通过Andorid studio 的Profile
点击Profile运行项目
然后会呈现下图
鼠标移动到CPU那里后,左键双击CPU后,如图:
Record,点击后,文案会变成stop;我们就可以在APP里操作,来到我们觉得卡顿或者有问题的功能里。点击stop就形成了我们trace一样的文件里。里面的操作都是一样的
然后剩下的按钮就和之前一样了 ,从上图可以看到也会有对应的四个tab,具体释义和上文相同。
通过这种方式我们通过了解卡顿的大概发生节点,来分析具体原因。