Android Performance: Traceview
Traceview可以记录方法运行的数据,如运行时间、调用次数等,帮助定位代码中的性能问题。
下面使用的代码可以在这里找到,运行后点击“BATCHING AND CACHING”,如图1所示,点击“COMPUTE SOME FIBONACCI NUMBERS”会开始计算一段斐波那契数列。
在Android Studio中打开Android Device Monitor,在右上角选择DDMS页面,在左边Devices下选中对应的应用,这里是com.example.android.mobileperf.compute,然后点击Devices工具栏中的Start Method Profiling按钮,如图2所示,出现一个对话框。
这里Trace based profiling会消耗较多的资源,影响性能。Android 4.4之后可以选择Sample-based profiling,以一定的的频率进行采样,速度较快。
在图2中选择Sample-based profiling,点击OK。之后点击应用上的“COMPUTE SOME FIBONACCI NUMBERS”按钮,稍等片刻运行完毕后,点击Devices工具栏中的Stop Method Profiling按钮,会显示出如图3所示的画面。
上方红框中有两行时序图,每一行代表一个线程;下面红框的列表中每一行代表一个方法,每个方法对应一种颜色。放大后如图4所示。
main线程的图中有很多彩色的方块,不同颜色的方块代表了方法,同一种颜色的方块总是成对出现,形成一个U形,U的左右两条边分别表示进入和离开方法。
回到全景图,可以看到main线程中间有有一长段连续的调用,在上面点击后,可以在下面的列表中看到对应方法的信息,如图5所示。
可见该方法是CachingActivity的computeFibonacci()
。Parent表示调用方法的位置,这里是在CachingActivity的onClick()
里被调用;Children表示在该方法被调用的子方法,这里是它自己,说明是递归调用。后面各栏还记录了方法占用CPU的时间、调用次数等参数。
在CachingActivity.java中可以找到计算斐波那契数列的方法如下:
public int computeFibonacci(int positionInFibSequence) { if (positionInFibSequence <= 2) { return 1; } else { return computeFibonacci(positionInFibSequence - 1) + computeFibonacci(positionInFibSequence - 2); } }
通过递归的方式计算斐波那契数列,存在重复计算的情况。修改为使用迭代计算,通过保留部分历史值避免重复计算:
public int computeFibonacci(int positionInFibSequence) { int prev = 0; int current = 1; int newValue; for (int i=1; i<positionInFibSequence; i++) { newValue = current + prev; prev = current; current = newValue; } return current; }
再次查看Traceview,如图6所示,现在computeFibonacci()
只会占用很少的时间。
另外,在图5也可以看到,计算斐波那契数列的方法运行在main线程上,导致界面卡顿。应当在单独线程执行计算。