1、DDMS与traceView的区别
DDMS是一个集调试、浏览、控制等操作为一体的工具箱,而traceView只是一个性能调优工具,可通过它查看程序中方法的执行效率等指标。
2、traceView的使用
traceView的开启有两种方式
①最简单的方式就是直接打开DDMS,选择一个进程,然后按上面的“Start Method Profiling”按钮,等红色小点变成黑色以后就表示TraceView已经开始工作了。然后进行手机操作,操作最好不要超过5s,因为最好是进行小范围的性能测试。然后再按一下刚才按的按钮,等一会就会出现上面这幅图,然后就可以开始分析了。
②第2种方式就是使用android.os.Debug.startMethodTracing();
和android.os.Debug.stopMethodTracing();
方法,将android.os.Debug.stopMethodTracing();放在结束调试的地方。当运行了这段代码的时候,就会有一个trace文件在/sdcard
目录中生成,也可以调用startMethodTracing(String traceName)
设置trace文件的文件名,最后你可以使用adb pull /sdcard/test.trace /tmp
命令将trace文件复制到你的电脑中,然后用DDMS工具打开就会出现第一幅图了。
上述两种方式都可以进行测试的开始,第一种方式适用于更大范围的调试,第二种更加的精确,可以在局部方法测试。
3、traceView中的指标
纵轴
TraceView界面下方表格中纵轴就是每个方法,包括了JDK的,Android SDK的,也有native方法的,当然最重要的就是app中你自己写的方法,有些Android系统的方法执行时间很长,那么有很大的可能就是你app中调用这些方法过多导致的。
每个方法前面都有一个数字,可能是全部方法按照Incl CPU Time 时间的排序序号(后面会讲到)
点一个方法后可以看到有两部分,一个是Parents,另一个是Children。
-
Parent表示调用这个方法的方法,可以叫做父方法
-
Children表示这个方法中调用的其他方法,可以叫做子方法
横轴
![](https://i-blog.csdnimg.cn/blog_migrate/532af8502f2f0337919c783bdc48a915.jpeg)
1. Incl Cpu Time
Incl Cpu Time表示方法top执行的总时间,假如说方法top的执行时间为10ms,方法a执行了1ms,方法b执行了2ms,方法c执行了3ms,方法d执行了4ms(这里是为了举个栗子,实际情况中方法a、b、c、d的执行总时间肯定比方法top的执行总时间要小一点)。public void top() {
a();
b();
c();
d();
}
而且调用方法top的方法的执行时间是100ms,那么:
Incl Cpu Time | ||
---|---|---|
top | 10% | |
a | 10% | |
b | 20% | |
c | 30% | |
d | 40% |
toplevel
的 Incl Cpu Time 是1110.943,而
io.bxbxbai.android.examples.activity.ExpandableLayoutMainActivity$SimpleAdapter.getItemView
方法的Incl Cpu Time为12.859,说明后者的Incl Cpu Time % 约为1.2%
2. Excl Cpu Time
理解了Incl Cpu Time以后就可以很好理解Excl Cpu Time了,还是上面top方法的栗子:
方法top 的 Incl Cpu Time 减去 方法a、b、c、d的Incl Cpu Time 的时间就是方法top的Excl Cpu Time 了
3. Incl Real Time
这个感觉和Incl Cpu Time 差不多,第7条会讲到。
4. Excl Real Time
同上
5. Calls + Recur Calls / Total
这个指标非常重要!
它表示这个方法执行的次数,这个指标中有两个值,一个Call表示这个方法调用的次数,Recur Call表示递归调用次数,看下图:
![](https://i-blog.csdnimg.cn/blog_migrate/9d0d8055007dea25db7913eafaab02b1.jpeg)
我选中了一个方法,可以看到这个方法的Calls + Recur Calls
值是14 + 0,表示这个方法调用了14次,但是没有递归调用
从Children这一块来看,很多方法调用都是13的倍数,说明父方法中有一个判断,但是这不是重点,有些Child方法调用Calls为26,这说明了这些方法被调用了两遍,是不是可能存在重复调用的情况?这些都是可能可以优化性能的地方。
6. Cpu Time / Call
重点来了!!!!!!!!!!
![](https://i-blog.csdnimg.cn/blog_migrate/bc0d5b8c21fa682c1858ad9f5ec7c7b8.jpeg)
这个指标应该说是最重要的,从上图可以看到,133这个方法的调用次数为20次,而它的Incl Cpu Time为12.859ms,那么133方法每一次执行的时间是0.643ms(133这个方法是SimpleAdapter
的getItemView
方法)
对于一个adapter
的getView
方法来说0.643ms是非常快的(因为这个adapter
中只有一个TextView
,我为了测试用的)
如果getView
方法执行时间很长,那么必然导致列表滑动的时候产生卡顿现象,可以在getView
方法的Children方法列表中找到耗时最长的方法,分析出现问题的原因:
-
是因为有过多的计算?
-
还是因为有读取SD卡的操作?
-
还是因为
adapter
中View
太复杂了? -
还是因为需要有很多判断,设置
View
的显示还是隐藏 -
还是因为其他原因…
7. Real Time / Call
Real Time 和 Cpu Time 我现在还不太明白它们的区别,我的理解应该是:
-
Cpu Time 应该是某个方法占用CPU的时间
-
Real Time 应该是这个方法的实际运行时间
为什么它们会有区别呢?可能是因为CPU的上下文切换、阻塞、GC等原因方法的实际执行时间要比Cpu Time 要稍微长一点。
总结
TraceView是一个非常强大的性能分析工具,因为Android 官网对这个工具的使用介绍文档很少,而且一些中文博客中写的也都是抄来抄去,没有讲到底怎么使用。
最近我在做这方面的性能分析,就慢慢琢磨了这么工具的使用,发现非常强大,写下来总结一下。
Android的性能分析工具还有很多,比如:
-
Eclipse Memory Analyzer Tool 来分析Android app的内存使用
-
Dump UI Hierarchy for UI Atomator,分析UI层级
-
systrace
-
其他