26
2017
09

Android性能优化之app启动时间测量

Android App启动

Android中App的启动通常有两种启动方式,分别为:

  • 冷启动 这种启动方式是在App的进程没有被创建过的情况下进行启动的,这个过程中需要先创建进程,然后
    启动Application,最后才会启动app的主Activity
  • 热启动 这种启动模式就是app已经启动过,并且进程还没有被清理掉,再去启动app时就不会创建进程了,直接
    启动主Activity

  了解以上两种启动方式之后如果我们要对app的启动速度进行优化,那么我们就需要对冷启动时Application的初始化进行优化,也要对主Activity的初始化进行优化,才能实现我们的启动优化的效果。而在app启动的过程中,从用户点击桌面图标到界面显示的这个过程中的中间过程是由系统控制的,我们能够控制的只有自己app的Application和主Activity。
在应用开发中往往影响app启动速度的问题主要集中在以下两个方面:

  • Application初始化耗时,一些app会在Application的onCreate方法中初始化一些常用的组件,特别是一些大型app,需要初始化
    的组件更多。
  • 主Activity的onCreate初始化耗时,在主Activity初始化时设置的布局过于复杂、布局层次深,自定义View绘制耗时,初始化数据
    等操作往往是导致耗时的原因。

测量app启动时间

在对app启动时间进行优化之前我们需要知道怎样去测量一个app的启动时间,才能帮助我们从数据上和视觉上实现最好的优化效果。

一、ActivityManager Log->Displayed Time

在启动app的时候Logcat会打印出ActivityManager的Log出来,其中有一行用于显示app启动时间的Log,我们需要知道显示时间时只需要执行如下命令,打印相关信息:

adb logcat -s ActivityManager

如果是在Linux环境下的话更可以通过如下命令过滤信息:

adb logcat -s ActivityManager |grep Displayed 

在点击需要测量的app图标,启动它,在终端会显示如下结果:

09-19 22:03:59.258  1833  1951 I ActivityManager: Displayed com.example.alexluo.myapplication/.MainActivity: +97ms

二、Activity的reportFullyDrawn方法,该方法从api 19开始有效

该方法用于向系统报告app已经启动完成绘制,需要系统统计启动时间,在开发中出于优化的目的,通常会先加载View,再延迟加载View需要的数据,我们可以通过这个方法来测量延迟加载数据所消耗的时间。
下面是模拟代码:


public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
               reportFullyDrawn();
            }
        },300);
    }

}

启动app时我们在终端打印ActivityManager的Log显示如下

09-19 22:17:30.746  1833  1951 I ActivityManager: Displayed com.example.administrator.myapplication2/.MainActivity: +78ms
09-19 22:17:30.986  1833  9676 I ActivityManager: Fully drawn com.example.administrator.myapplication2/.MainActivity: +318ms

在示例代码中从Displayed显示时间为78ms,Fully drawn时间为318ms,我们延迟了300毫秒执行reportFullyDrawn方法,可以大概推算出剩下的18ms为Handler消息处理和系统接收并处理reportFullyDrawn方法的时间

三、Android Studio MethodTracing工具(使用方法)

Android Studio自带Method Tracing工具,可以使用该工具来分析和记录方法的执行时间,以此来分析性能问题
在需要检测的代码前后分别添加如下代码:

Debug.startMethodTracing();
Debug.stopMethodTracing();

例如:



public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Debug.startMethodTracing(); testAppStart(); Debug.stopMethodTracing(); } private void testAppStart(){ try{ Thread.sleep(3000); }catch (InterruptedException e){ } } } 

在上面的代码中我们模拟一个耗时方法,Thread睡眠3000毫秒,然后在Activity的onCreate中调用该方法,并用Debug的Method Tracing来跟踪执行时间。
在app启动的时候点击Android Studio Monitor中的被红色圈住的按钮。

这里写图片描述

然后会生成一个trace文件,如下图所示:

这里写图片描述

该文件具体记录了方法的执行时间,可以通过该方法判断是哪个地方执行耗时。
如上图所示,可以查找到我们定义的testAppStart方法的执行时间,下面是常用菜单的介绍:

底部栏时间栏:

菜单名 说明
Name 执行方法名
Invocation Count 调用次数
Inclusive Time(us) 该方法及其内部调用的方法执行时间
Exclusive Time(us) 该方法执行时间,不包括内部子方法执行时间

顶部图表栏:

  • Wall Clock Time 被调用方法从开始到返回的真正CPU时间
  • Thread Time 线程调度时间,如果线程中断,这个中断过程中的时间会被排除,就会小于Wall Clock Time

四、Systrace

该工具从4.1开始有,从4.3开始可以通过代码插入分析代码执行过程,Systrace可以统计和生成系统运行时的具体报告,
包括绘图系统,输入系统,资源加载等系统模块的执行过程

  • 在启动的时候调用Trace.beginSection和Trace.endSection
  • 点击Android Studio Tools->Android Device Monitor启动Monitor
  • 选中设备,点击如下按钮Capture system弹出systrace配置窗口

这里写图片描述

设置窗口:

这里写图片描述

然后就可以生成trace文件,并用Chrome浏览器打开,如下图所示:

这里写图片描述

例如:
需要测试的代码:


@Override
protected void onCreate(Bundle savedInstanceState) {
    Trace.beginSection("traceTest");
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Trace.endSection();
}


最后生成的trace文件,通过放大后针对我们的代码段的trace结果如图所示:

这里写图片描述

五、ScreenRecord,可以通过屏幕录像来分析启动时间

被录制好的视频会显示执行时间,我们导出视频之后可以通过一些逐帧动视频查看工具统计启动时间,
可以通过adb命令启动屏幕录制:

adb shell screenrecord --bugreport /sdcard/app_start.mp4
上一篇:Android Apk解析 下一篇:Android Native内存泄漏诊断