测量Activity 的启动时间

如何获得app的启动时间?

我也在想这个问题。

当我在framework 代码上做这类测量的时候,我可以精确的得出我需要的东西。但是非framework 开发者如何从普通构建获得自己需要的信息呢?

blob.png

一 、直接看log

幸运的是,这个信息是存在的,如果你运行的是4.4(Kitkat)以后的版本,你就可以得到。

你只要启动你的activity ,然后直接在logcat里面查看,寻找这样的log:

ActivityManager: Displayed com.android.myexample/.StartupTiming: +768ms

这个信息在activity 窗口完成所有的启动事件之后,第一次绘制的时候输出。这个时间包括了从启动进程到第一次布局与绘制的所有时间。这基本上是你需要知道的主要时间。它不包含用户点击app图标然后系统开始准备启动activity的时间,这是ok的,因为作为一个开发者你无法影响这个时间,所以没有必要去测量它。

相反,它包含的是在启动时加载代码,初始化类所用的时间。里面都是你真正想测量的时间,因为它们才是你能优化也应该去优化的东西。

二、调用Activity的reportFullyDrawn()方法

前面所提到的 'Displayed' 时间是自动报告的。 快速测量启动初始化需要多久。但是假如你还异步加载一些其它的内容,想知道所有的东西加载完成,绘制需要多久该怎么做呢?

这种情况下,你就需要调用Activity的reportFullyDrawn()。它将在log里报告从apk初始化(和前面Displayed的时间是一样的)到reportFullyDrawn() 方法被调用用了多长时间。

reportFullyDrawn()方法显示的log也是类似这样:

ActivityManager: Displayed com.android.myexample/.StartupTiming: +768ms

译者注:在4.4上调用reportFullyDrawn()方法会崩溃(但是log还是能正常打印),提示需要UPDATE_DEVICE_STATS权限 ,但是这个权限只有系统app才能授权。解决的办法是这样调用:

try{
    reportFullyDrawn();
}catch(SecurityException e){
}

三、使用screenrecord命令

还有一种测量启动时间的方法也值得一提,那就是screenrecord命令。

首先启动带—bugreport选项(它可以在frames 中添加时间戳-应该是L中的特性)的screenrecord 命令:

 $ adb shell screenrecord --bugreport /sdcard/launch.mp4

然后点击app的图标,等待app显示,ctrl-C screenrecord, 使用adb pull命令把文件导出到电脑。

 $ adb pull /sdcard/launch.mp4

现在你可以打开录制视频看看发生了什么。你需要一个能逐帧查看的视频播放器(mac上的Quicktime 就可以,不清楚其它os上什么播放器这个功能最好使)。现在逐帧播放,注意视频的上方有一个frame 时间戳。

一直往前直到你发现app图标高亮了为止。这个时候系统已经处理了图标上的点击事件,开始启动app了,记录下这一帧的时间。继续播放帧直到你看到了app整个UI的第一帧为止。根据不同情况(是否有启动窗口,是否有启动画面等等),事件和窗口发生的实际顺序可能会有不同。对于一个简单的app来说,你会首先见到启动窗口,然后渐变出app真实的UI。在你看到UI上的任何内容之后,你应该记录下第一帧,这时app完成了布局和绘制,准备开始显示出来了。同时也记录下这一帧所发生的时间。

现在把这两个时间相减 ((UI displayed) - (icon tapped)); 得到app从点击到绘制就绪的所有时间。虽然这个时间包含了进程启动之前的时间,但是至少它可以用于跟其他app比较。

现在你知道如何计算启动时间了,不管你用什么方法,能让app变快就是了。

英文原文:Measuring Activity Startup Time