测试基础 正确使用 Android 性能分析工具——TraceView

恒温 · 2016年06月02日 · 最后由 liuxiaoyao0602 回复于 2016年07月24日 · 3110 次阅读
本帖已被设为精华帖!

原文来自: http://bxbxbai.github.io/2014/10/25/use-trace-view/

作者的 github https://github.com/bxbxbai

前面唠叨

最近公司 app 中有些列表在滑动的时候会有卡顿现象,我就开始着手解决这些问题,解决问题之前首先要分析列表滑动的性能瓶颈在什么地方。因为之前不会正确使用 TraceView 这个工具,主要是看不懂 TraceView 界面下方数据指标的值代表什么意思…以前我用StopWatch类来分析性能,现在觉得弱爆了…不过有些地方StopWatch工具类还是很简单好用的~

网上可以找了很多博客来介绍这个工具的使用方法,很多都是讲解了一些一些就会的方法,讲一个大概,包括 StackOverFlow 上我也没有找到很好的讲解 TraceView 各个数据指标代码什么意思的回答

因为我要解决列表滑动的卡顿问题,就必须要找到导致卡顿现象的原因,我就在 StackOverFlow 上找着别人零散的回答慢慢琢磨这个工具的使用方法。现在我学会了,至少能看懂每个指标什么意思,最后发现这个工具实在太强大了!!!

TraceView 界面

现来看一下整个界面的图,整个界面包括上下两部分,上面是你测试的进程中每个线程的执行情况,每个线程占一行;下面是每个方法执行的各个指标的值

上面一部分是你测试进程的中每个线程运行的时间线,下图中可以可以看到,主要只有一个 main 线程在执行,因为我滑动了一下列表,main 线程(UI 线程)正在进行绘制 View 呢~~

然后我点击了序号为 133 的一个方法io.bxbxbai.android.examples.activity.ExpandableLayoutMainActivity$SimpleAdapter.getItemView,就会出现两部分数据:

  • Parents
  • Children

Parents 表示调用 133 这个方法的父方法,可以看到序号为 130。Children 表示方法 133 调用的其他方法,可以看到有好几个方法。

如何使用 TraceView

因为这次我主要是分析列表滑动卡顿问题,我就讲讲我是怎么使用这个工具的,并且我是怎么分析的。

使用 TraceView 主要有两种方式:

  1. 最简单的方式就是直接打开 DDMS,选择一个进程,然后按上面的 “Start Method Profiling” 按钮,等红色小点变成黑色以后就表示 TraceView 已经开始工作了。然后我就可以滑动一下列表(现在手机上的操作肯定会很卡,因为 Android 系统在检测 Dalvik 虚拟机中每个 Java 方法的调用,这是我猜测的)。操作最好不要超过 5s,因为最好是进行小范围的性能测试。然后再按一下刚才按的按钮,等一会就会出现上面这幅图,然后就可以开始分析了。

  2. 第 2 种方式就是使用android.os.Debug.startMethodTracing();android.os.Debug.stopMethodTracing();方法,当运行了这段代码的时候,就会有一个 trace 文件在/sdcard目录中生成,也可以调用startMethodTracing(String traceName) 设置 trace 文件的文件名,最后你可以使用adb pull /sdcard/test.trace /tmp 命令将 trace 文件复制到你的电脑中,然后用 DDMS 工具打开就会出现第一幅图了

第一种方式相对来说是一种简单,但是测试的范围很宽泛,第二中方式相对来说精确一点,不过我个人喜欢使用第一种,因为简单,而且它是检测你的某一个操作。因为第二中更适合检测某一个方法的性能,其实也没有那种好,看使用的场景和喜好了。。。

看懂 TraceView 中的指标

其实我今年 7 月份就已经开始使用 TraceView 工具了,但是当时不懂其中每个指标的含义,就没注意到它强大的地方。看不懂界面下方表格中的指标,这些数据其实一点意义都没有。

网上包括 Android 官网也没有对 TraceView 工具的使用有详细的说明文档,这点确实比较蛋疼。

纵轴

TraceView 界面下方表格中纵轴就是每个方法,包括了 JDK 的,Android SDK 的,也有 native 方法的,当然最重要的就是 app 中你自己写的方法,有些 Android 系统的方法执行时间很长,那么有很大的可能就是你 app 中调用这些方法过多导致的。

每个方法前面都有一个数字,可能是全部方法按照 Incl CPU Time 时间的排序序号(后面会讲到)

点一个方法后可以看到有两部分,一个是 Parents,另一个是 Children。

  • Parent 表示调用这个方法的方法,可以叫做父方法

  • Children 表示这个方法中调用的其他方法,可以叫做子方法

横轴

横轴上是很多指标,这些指标表示什么意思真的困扰了我很长一段时间。。。

能够很衡量一个方法性能的指标应该只有时间了吧? 一个方法肯定就是执行时间越短约好咯~~

1. Incl Cpu Time

define inclusive : 全包括的

上图中可以看到0(toplevel) 的 Incl Cpu Time 占了 100% 的时间,这个不是说 100% 的时间都是它在执行,请看下面代码:

public void top() {
    a();
    b();
    c();
    d();
}

Incl Cpu Time 表示方法 top 执行的总时间,假如说方法 top 的执行时间为 10ms,方法 a 执行了 1ms,方法 b 执行了 2ms,方法 c 执行了 3ms,方法 d 执行了 4ms(这里是为了举个栗子,实际情况中方法 a、b、c、d 的执行总时间肯定比方法 top 的执行总时间要小一点)。

而且调用方法 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%

这个指标表示 这个方法以及这个方法的子方法(比如 top 方法中的 a、b、c、d 方法)一共执行的时间

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 表示递归调用次数,看下图:

我选中了一个方法,可以看到这个方法的Calls + Recur Calls 值是 14 + 0,表示这个方法调用了 14 次,但是没有递归调用

从 Children 这一块来看,很多方法调用都是 13 的倍数,说明父方法中有一个判断,但是这不是重点,有些 Child 方法调用 Calls 为 26,这说明了这些方法被调用了两遍,是不是可能存在重复调用的情况?这些都是可能可以优化性能的地方。

6. Cpu Time / Call

重点来了!!!!!!!!!!

这个指标应该说是最重要的,从上图可以看到,133 这个方法的调用次数为 20 次,而它的 Incl Cpu Time 为 12.859ms,那么 133 方法每一次执行的时间是 0.643ms(133 这个方法是SimpleAdaptergetItemView方法

对于一个adaptergetView方法来说 0.643ms 是非常快的(因为这个adapter中只有一个TextView,我为了测试用的)

如果getView方法执行时间很长,那么必然导致列表滑动的时候产生卡顿现象,可以在getView方法的 Children 方法列表中找到耗时最长的方法,分析出现问题的原因:

  • 是因为有过多的计算?
  • 还是因为有读取 SD 卡的操作?
  • 还是因为adapterView太复杂了?
  • 还是因为需要有很多判断,设置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
  • 其他

下图这一条工具栏中有很多性能分析工具~~~

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 18 条回复 时间 点赞

只适用于 java 层,底层用不了。。。。

加精. 写的很详细. traceview 工具代表的是底层 trace 技术的应用. 是行业做 profile 常用的技术手段. 非常的精准有效.
我一直想了解的点是在执行 android.os.Debug.startMethodTracing() 之后, android 的 runtime 到底是干了什么事情. 如果能把这个技术提取出来, 就可以突破那个 5s 的限制自由的 trace 整个调用链了. trace 特定的 api 调用.

#2 楼 @seveniruby 目前看到写最好的了。

#3 楼 @lihuazhang android 的 runtime 的资料太少了 我看 am 命令也能 profile 任何进程. 貌似是跟 art 自身的 trace 特性有关. 不知道 art 是如何跟 jvm 一样也动态加 trace 的

分享下 ios 的呢?

这篇写的很详细,赞一个

赞:)

匿名 #8 · 2016年06月03日

Mark 学习

好早之前看到过 应该是 traceView 写的非常清楚的一篇了 :)

赞,昨天在 MQC 的公众号推出来的消息,整准备收藏,在这里看到了

#10 楼 @wyb199026 我推荐给他们的

之前跟组内同学分享过这个,还是非常强大的,除了分析,还能定制输出文本报告,做抽样分析和质量报告输出。可以帮助开发发现深层次的问题。

traceview 这一块其实可以做深度挖掘,依赖 IDE 太有限,通过解析 traceview 文件,可以将自己关注的进程以及方法过滤出来分析问题

学习了,马上上手

太赞了!受益匪浅!!!

TraceView 能适配 ios 吗? 目前服务的客户主要使用 ios,可否可以推荐几个测试工具

李雷雷 [该话题已被删除] 中提及了此贴 06月29日 18:10
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册