精通安卓性能优化-第六章(二)

Tracing

一旦发现了什么需要花费太多的时间,你很可能希望可以了解更多的细节,哪个方法是罪魁祸首。你可以在tracing-specific方法帮助下创建trace文件,通过Traceview工具去分析他们。

Debug.startMethodTracing()

Android提供了Debug.startMethodTracing()方法创建trace文件,可以用来使用Traceview工具去调试和分析你的应用。Debug.startMethodTracing()方法有四个变种:
(1) startMethodTracing
(2) startMethodTracing(String traceName)
(3) startMethodTracing(String traceName, int bufferSize)
(4) startMethodTracing(String traceName, int bufferSize, int flags)
traceName参数指定了写trace信息的文件名。(如果文件已经存在,将被截断)需要保证你的应用有这个文件的写权限。(默认的,文件将被在SD卡创建,除非给出了一个绝对路径)bufferSize参数指定了trace文件的最大值。Trace信息可以使用很多空间,你的存储器可能是有限的,所以尝试去使用一个可接受的值(默认8M)。安卓现在只定义一个标志,Debug.TRACE_COUNT_ALLOCS,所以flags参数可以被设置为0或者Debug.TRACE_COUNT_ALLOCS(为了从Debug.startAllocCounting()添加结果到trace,即分配内存的数量和合计大小)。Android同样提供了Debug.stopMethodTracing()方法,你可能已经猜到,是停止tracing的方法。使用方式和前面的测量很相似,如Listing 6-5所示。
Listing 6-5 开启Tracing

Debug.startMethodTracing("/sdcard/awesometrace.trace");

// 执行你希望跟踪的操作
BigInteger fN = Fibonacci.computeRecursivelyWithCache(100000);

Debug.stopMethodTracing();

// 在/mnt/sdcard下面生成一个awesometrace.trace文件,通过Eclipse DDMS获取它

Trace文件将会保存到你的Android设备上(或者模拟器),所以需要复制文件到你的PC,比如使用DDMS或者adb pull指令。

使用Traceview 工具

Android SDK带有一个Traceview工具,可以使用这些trace文件,给你一个图形表示的trace,如Figure 6-1所示。你可以在SDK的工具目录找到这个Traceview工具,通过traceview awesometrace.trace命令去启动Traceview。

图6-1 Traceview窗口


trace基本上包括所有的函数调用和这些调用使用了多少时间,多少次调用。7列分别显示了:
(1) Name:方法的名字
(2) Incl %:方法所花费的时间(包含子方法)
(3) Inclusive:方法花费的毫秒数(包含子方法)
(4) Excel %:方法花费时间所占的比例(包含子方法)
(5) Exclusive:方法花费的毫秒数(不包括子方法)
(6) Calls+RecurCalls/Total:调用的数量和递归调用
(7) Time/Call:每个调用平均时间,单位毫秒
比如,14个BigInteger.multiply()的调用总共使用了10.431毫秒,或者745微秒每个调用。因为当tracing开启后,VM将运行的更加慢,不要将时间值认为操作所需的绝对时间。相反,使用这些时间值只是简单的去决定哪个方法运行更快。

如果你点击一个方法名字,Traceview将给出指定方法更加细节的信息。如Figure 6-2所示,这包括:
(1) Parents (调用这个方法的方法)
(2) Children(这个方法调用的方法)
(3) Parents while recursive(如果方法是递归的)
(4) Children while recursive(如果方法是递归的)
就像你在Figure 6-2可以看到的,大多数时间花费在四个方法上:
(1) BigInteger.multiply()
(2) BigInteger.pow()
(3) BitInteger.add()
(4) BigInteger.shiftLeft()
尽管我们已经在第一章知道哪里是瓶颈,Traceview允许你非常快的决定瓶颈在哪里而不需要非常昂贵的查找。在这个特殊的实例下,你可以很快的看到BigInteger.multiply()是最耗时的,紧接着是BigInteger.pow()。这不惊奇,因为相乘直观上比加BigInteger.add()和移位BigInteger.shiftLeft()更加复杂。

图6-2 一个方法的详细信息


在窗口的上端可以看到主线程的时间线。可以选择时间线上一段特定的区域去放大,通过双击缩小。使自己武装Traceview工具,学习怎么样从一个方法到另外一个方法浏览。Hint:很简单,只需要点击方法的名字。
因为当tracing开启JIT编译器被禁用,你得到的结果可能会有些误导。实际上,你可能会想一个方法需要某个时间值,理想上它会快很多,因为它会通过JIT编译器被编译成native代码。同样的,trace不会显示native方法花费多少时间。比如,Figure 6-1给出了NativeBN.Bn_mul()和NativeBN.BN_exp()的调用,如果你点击这些方法,不会看到他们可能调用了什么方法。

Traveview in DDMS

跟踪方法调用和使用Traceview的另一种方式是直接通过Eclipse DDMS视图产生一个trace文件。在你选择一个特定的进程后,你可以点击Start Method Profiling图标,再次点击会停止分析。一旦停止分析,trace在Eclipse Debug视图成为可见的,可以使用Traceview查看。Figure 6-3 给出了如何从DDMS视图开始method profiling。Figure 6-4给出了在Debug视图的method profiling view。

图6-3 在DDMS视图开始method profiling


图4 在Debug视图的Method profiling


就像你在Figure 6-4看到的,可以看到多个线程的timeline。
Traceview不是完美的,然而他可以帮你深入观察实际执行了什么代码,哪里可能是瓶颈。为了达到更好的性能,这将是你首选的工具之一,帮你发现需要聚焦的地方。

TIP:完成调试和分析后记得删除trace文件。可以使用Eclipse DDMS视图删除文件。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值