Traceview是一个图形化的查看器, 它可以查看Debug类在代码中创建的日志. Traceview可以帮助你调试APP并分析它的性能.
当你拥有一个trace log文件(通过添加trace代码在你的APP或者通过DDMS获得), 你可以记载log文件到traceview中, 这会在两个面板中显示log数据:
l 一个时间线面板 – 描述什么时候每个线程和方法启动和停止.
l 一个分析面板 – 提供一个总览, 它描述了一个方法内发生了什么事情.
时间线面板:
图1展示了一个时间线面板的特写. 每个线程的执行都被显示在它自己的行中, 并随着时间推移向右增加. 每个方法都显示以不同的颜色显示(颜色会以循环方式重用, 从最长时间的方法开始). 细线下方的第一行展示了所有选中方法的执行时间(从开始到退出).
图1, Traceview时间线面板.
分析面板:
图2展示了分析面板, 它显示的是某个方法中所有的时间开销. 表格展示了全局和独立的时间(作为总时间的百分比). 独立时间指的是在方法中的时间开销. 全局总时间指的是方法内花的时间外加任何调用的函数所花的时间. 这里将调用方法作为”parent”, 被调用的方法称为”children”. 当一个方法被选中(点击了它), 它会展开来展示自己的parent和children. Parent显示为紫色背景, children则显示为黄色背景. 最后一列显示了该方法调用的方法加上递归调用的次数. The last column shows the number of calls out of the total numberof calls made to that method. 在这个view中, 我们可以看到有14个调用LoadListener.nativeFinished(); 从时间线面板可以看出其中一个消耗了不寻常的长时间.
图2, Traceview的分析面板.
要使用Traceview, 你需要生成一个包含trace信息的日志文件. 有两种方法生成trace文件:
l 在代码中引入Debug类并调用它的方法, 比如startMethodTracing()和stopMethodTracing(),来开始和停止记录trace信息到硬盘. 这个方法非常精确, 因为你可以准确的在代码中指定从哪里开始从哪里停下记录trace数据.
l 使用DDMS的方法(method)分析功能来生成trace日志. 这种办法精确度差一点因为你没有修改代码, 而是要用DDMS指定什么时候启动和停止日志. 尽管你拥有对精确启动和停止的更少控制, 但是这个方法在你没有对代码的访问权限的时候还是十分有用, 或者有可能你根本就不需要精确的日志时间.
在你开始获得trace日志之前, 小心这些限制:
l 如果你使用Debug类, 你的APP必须拥有写外部存储的权限(WRITE_EXTERNAL_STORAGE).
l 如果你使用DDMS:
n Android 2.1及更早版本必须拥有一个SD卡, 并且你的APP必须用权限写SD卡.
n Android 2.2及更高版本中, 不需要SD卡. Trace日志文件直接被stream到你的开发设备.
本文聚焦于使用Debug类来生成trace数据. 更多关于使用DDMS生成trace数据的信息可以参考Using theDalvik Debug Monitor Server.
要创建trace文件, 引入Debug类并调用其中一个startMethodTracing()方法. 在该方法中, 你需要为trace文件指定一个基础的名称. 要停止trace, 调用stopMethodTracing(). 这些方法会启动和停止整个虚拟的设备的方法. 栗如, 你可以在Activity的onCreate()方法中调用strategyMethodTracing(), 并在onDestroy()中调用stopMethodTracing()方法.
//start tracing to "/sdcard/calc.trace"
Debug.startMethodTracing("calc");
// ...
// stop tracing
Debug.stopMethodTracing();
当你的APP调用了startMethodTracing()的时候, 系统会创建一个叫做
执行代码会在分析开启的时候运行的很慢. 所以不要试图从分析结果中生成绝对的时间(比如, 某功能消耗的2.5秒来运行). 只能跟其它的分析输出一起对比相对的时间, 所以你可以看到相对于分析运行之前, 运行速度会变得更快或者更慢.
在Android 4.4及更高版本中, 你可以使用基于采样的分析来减少运行时对性能的影响. 要启用采样分析, 调用startMethodTracingSampling()并指定一个采样间隔. 系统将会定期的采样直到调用stopMethodTracing().
当你的APP运行了并且成功的在设备或模拟器上创建了trace文件, 你必须将它们copy到你的开发电脑上. 你可以使用adb pull来copy文件. 这是一个栗子, 它从默认的路径将calc.trace文件copy到了/tmp目录.
adb pull /sdcard/calc.trace /tmp
要运行Traceview并查看trace文件:
l 启动AndroidDevice Monitor.
l 在Android DeviceMonitor工具栏中, 点击DDMS并选择一个进程.
l 点击StartMethod Profiling图标来启动方法分析.
l 在分析完成之后, 点击Stop MethodProfiling图标来显示traceview.
注意: 如果你正在试图查看一个通过ProGuard编译的APP的trace日志, 有些方法和成员名称可能被混淆. 你可以使用ProGuard mapping.txt文件来弄清楚原始的未混淆的名字. 更多信息可以参考ProGuard.
Dmtracedump是一个协助分析trace日志文件的工具, 它可以为你提供一种替代方法来生成图表化的调用栈图. 该工具使用Graphviz Dot实用工具来创建图形输出, 所以你需要在运行dmtracedump之前先安装Grphviz.
Dmtracedump工具生成调用栈数据的树形图表, 每个节点代表一次调用. 它用剪头来显示调用流(从parent点到children点). 下图是一个栗子:
图3, dmtracedump截图.
对于每个节点, dmtracedump显示一个 callname(
l
l
l
Dmtracedump的用法是:
dmtracedump [-ho] [-s sortable] [-d trace-base-name] [-g outfile] <trace-base-name>
该工具会从
选项 |
描述 |
-d |
Diff with this trace name |
-g |
生成的输出文件的名字 |
-h |
开启HTML输出 |
-o |
转存trace文件而不是分析 |
-d |
URL基础可排序的JavaScript文件的位置. |
-t |
图表中包含的子节点的最小阈值(parent总时间中child总时间的百分比), 如果没有设置, 那么默认的阈值是20%. |
线程:
Traceview日志不能良好的处理线程, 这会导致两个问题:
1. 如果一个线程在分析期间退出了, 那么线程的名字将会不被发出(emitted)(在Android 5.1中修复).
2. VM会重用线程ID. 如果一个线程停止了, 另一个线程开始, 它们可能使用相同的ID.
Traceview随时间推移记录日志, 并显示执行数据, 每个线程的时间线, 和调用堆栈. 它可以跟踪源码中的性能问题.
使用流程:
1. 连接你的设备和电脑.
2. 打开Android Studio中的APP, 创建源代码并运行在你的设备中.
3. 启动Android Device Monitor, Tools>Android>Android Device Monitor.
4. 确保你的设备和APP包显示在Device(DDMS)或者Windows(Hierarchy Viewer)页面中. 如果有必要, 选择Windows>ResetPerspective来返回到默认的面板排列.
5. 点击DDMS按钮, 因为Traceview是DDMS工具中的其中一个.
6. 选择你要分析的APP.
7. 点击开始方法分析按钮.
8. 在Profiling Options弹框中:
a) 选择Sample based profiling.
b) 保持默认的采样率:1000ms.
c) 点击OK
9. 跟你的APP交互. 如果你在意性能问题, 用户体验, 那么执行那些相关的操作.
10. 点击停止方法分析按钮
11. 等待trance加载. 如果你记录的时间较长这可能会画上一点时间.
12. Traceview有两个面板, 时间线面板和分析面板.
13. 使用底部的搜索框来过滤你的分析结果. 比如, 如果你对查找某个函数的运行时间有兴趣, 你可以搜索它, 这时工具会高亮它的时间线.
14. 时间线面板使你可以可视化你的代码执行过程.
a) 每行显示一个线程.
b) 时间线中的每个栏表示一个正在执行的方法.
c) 每个颜色表示一个不同的方法; 每次一个方法执行, 你就会看到一个相同颜色的栏.
d) Bar的宽度代表方法运行时间的长短.
15. 当你缩小这个界面的时候, 会有一个bar来指示执行的方法.
16. 放大这个图表, 每个方法的bar会扩展为一个有颜色的U形, U形的左侧代表起始, 右侧则代表方法执行的结束.
17. 分析面板展示一个方法的列表.
a) 选择一个方法来查看谁调用的它(parent)以及它调用了谁(children).
b) 选中的方法还会在时间线中高亮
c) 列显示了独占的和全局的CPU和实时情况, 百分比, 比例, 和一个方法被调用的频率.
d) 独占时间(exclusive time)是方法本身所花费的时间, 它可以帮助你找到指定方法内的问题.
e) 全局时间(inclusive time)是方法和它所有调用的方法的时间, 可以帮助你找出调用树中的问题.
f) Call+REC这一列演示了一个方法的递归调用内容, 它可以帮助你跟踪性能问题.
参考: http://developer.android.com/tools/debugging/debugging-tracing.html