Android Performance: Traceview

  Traceview可以记录方法运行的数据,如运行时间、调用次数等,帮助定位代码中的性能问题。

  下面使用的代码可以在这里找到,运行后点击“BATCHING AND CACHING”,如图1所示,点击“COMPUTE SOME FIBONACCI NUMBERS”会开始计算一段斐波那契数列。

图1

图1

  在Android Studio中打开Android Device Monitor,在右上角选择DDMS页面,在左边Devices下选中对应的应用,这里是com.example.android.mobileperf.compute,然后点击Devices工具栏中的Start Method ProfilingStart Method Profiling按钮,如图2所示,出现一个对话框。

图2

图2

这里Trace based profiling会消耗较多的资源,影响性能。Android 4.4之后可以选择Sample-based profiling,以一定的的频率进行采样,速度较快。

  在图2中选择Sample-based profiling,点击OK。之后点击应用上的“COMPUTE SOME FIBONACCI NUMBERS”按钮,稍等片刻运行完毕后,点击Devices工具栏中的Stop Method ProfilingStop Method Profiling按钮,会显示出如图3所示的画面。

图3

图3

上方红框中有两行时序图,每一行代表一个线程;下面红框的列表中每一行代表一个方法,每个方法对应一种颜色。放大后如图4所示。

图4

图4

main线程的图中有很多彩色的方块,不同颜色的方块代表了方法,同一种颜色的方块总是成对出现,形成一个U形,U的左右两条边分别表示进入和离开方法。

  回到全景图,可以看到main线程中间有有一长段连续的调用,在上面点击后,可以在下面的列表中看到对应方法的信息,如图5所示。

图5

图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()只会占用很少的时间。

图6

图6

  另外,在图5也可以看到,计算斐波那契数列的方法运行在main线程上,导致界面卡顿。应当在单独线程执行计算。