Android 中如何计算 App 的启动时间?

摘要:
如何使用python或直接使用adb命令计算apk的启动时间?这是标准应用程序的开始时间(请注意,Android 5.0之前的手机没有WaitTime值):

利用python或者直接用adb命令怎么计算apk的启动时间呢?就是计算从点击图标到apk完全启动所花费的时间。比如,对游戏来说就是点击游戏图标到进入到登录界面的这段时间。

已知的两种方法貌似可以获取,但是感觉结果不准确:一种是,adb shell am start -w packagename/activity,这个可以得到两个值,ThisTime和TotalTime,不知道两个有什么区别,而且与实际启动时间不匹配,两者相加都可能比实际启动时间小(测试游戏的时候差别更大);另外一种是通过adb logcat的方式,感觉获取的结果也与实际有差别。

应用第一次启动

也就是我们常说的冷启动,这时候你的应用程序的进程是没有创建的. 这也是大部分应用的使用场景.用户在桌面上点击你应用的 icon 之后,首先要创建进程,然后才启动 MainActivity.
这时候adb shell am start -w packagename/MainActivity 返回的结果,就是标准的应用程序的启动时间(注意 Android 5.0 之前的手机是没有 WaitTime 这个值的):

  1.  adb shell am start -W com.media.painter/com.media.painter.PainterMainActivity
  2. Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.media.painter/.PainterMainActivity }
  3. Status: ok
  4. Activity: com.media.painter/.PainterMainActivity
  5. ThisTime: 355
  6. TotalTime: 355
  7. WaitTime: 365
  8. Complete

总共返回了三个结果,我们以 WaitTime 为准.

关于ThisTime/TotalTime/WaitTime的区别,下面是其解释:

“adb shell am start -W ”的实现在 frameworksasecmdsamsrccomandroidcommandsamAm.java 文件中。其实就是跨Binder调用ActivityManagerService.startActivityAndWait() 接口(后面将ActivityManagerService简称为AMS),这个接口返回的结果包含上面打印的ThisTime、TotalTime时间.

Android 中如何计算 App 的启动时间?第1张

  • startTime记录的刚准备调用startActivityAndWait()的时间点

  • endTime记录的是startActivityAndWait()函数调用返回的时间点

  • WaitTime = startActivityAndWait()调用耗时。

ThisTime、TotalTime 的计算在 frameworksaseservicescorejavacomandroidserveramActivityRecord.java 文件的 reportLaunchTimeLocked() 函数中。

Android 中如何计算 App 的启动时间?第2张

我们来解释下代码里curTime、displayStartTime、mLaunchStartTime三个时间变量.

  • curTime表示该函数调用的时间点.

  • displayStartTime表示一连串启动Activity中的最后一个Activity的启动时间点.

  • mLaunchStartTime表示一连串启动Activity中第一个Activity的启动时间点.

正常情况下点击桌面图标只启动一个有界面的 Activity,此时 displayStartTime 与mLaunchStartTime 便指向同一时间点,此时 ThisTime=TotalTime。另一种情况是点击桌面图标应用会先启动一个无界面的 Activity 做逻辑处理,接着又启动一个有界面的Activity,在这种启动一连串 Activity 的情况下(知乎的启动就是属于这种情况),displayStartTime 便指向最后一个 Activity 的开始启动时间点,mLaunchStartTime 指向第一个无界面Activity的开始启动时间点,此时 ThisTime!=TotalTime。这两种情况如下图:

Android 中如何计算 App 的启动时间?第3张

在上面的图中,我用①②③分别标注了三个时间段,在这三个时间段内分别干了什么事呢?

  • 在第①个时间段内,AMS 创建 ActivityRecord 记录块和选择合理的 Task、将当前Resume 的 Activity 进行 pause

  • 在第②个时间段内,启动进程、调用无界面 Activity 的 onCreate() 等、 pause/finish 无界面的 Activity

  • 在第③个时间段内,调用有界面 Activity 的 onCreate、onResume

看到这里应该清楚 ThisTime、TotalTime、WaitTime 三个时间的关系了吧:

  • WaitTime 就是总的耗时,包括前一个应用 Activity pause 的时间和新应用启动的时间;

  • ThisTime 表示一连串启动 Activity 的最后一个 Activity 的启动耗时;

  • TotalTime 表示新应用启动的耗时,包括新进程的启动和 Activity 的启动,但不包括前

一个应用 Activity pause 的耗时。也就是说,开发者一般只要关心 TotalTime 即可,这个时间才是自己应用真正启动的耗时。

Event log中 TAG=am_activity_launch_time 中的两个值分表表示 ThisTime、TotalTime,跟通过 “adb shell am start -W ” 得到的值是一致的。

最后再说下系统根据什么来判断应用启动结束。我们知道应用启动包括进程启动、走 Activity生命周期 onCreate/onResume 等。在第一次 onResume 时添加窗口到WMS中,然后measure/layout/draw,窗口绘制完成后通知 WMS,WMS 在合适的时机控制界面开始显示(夹杂了界面切换动画逻辑)。记住是窗口界面显示出来后,WMS 才调用reportLaunchTimeLocked() 通知 AMS Activity 启动完成。

最后总结一下,如果只关心某个应用自身启动耗时,参考TotalTime;如果关心系统启动应用耗时,参考WaitTime;如果关心应用有界面Activity启动耗时,参考ThisTime。

1.2 应用非第一次启动

如果是你按Back键,并没有将应用进程杀掉的话,那么执行上述命令就会快一些,因为不用创建进程了,只需要启动一个Activity即可。这也就是我们说的应用热启动。

2 游戏启动场景

游戏启动的话,就不适用用命令行的方法来启动了,因为从用户点击桌面图标到登录界面,既有系统的部分也有游戏自己的部分。

2.1 系统部分

游戏也有一个 Activity,所以启动的时候还是会去启动这个 Activity,所以系统启动部分也就是用户点击桌面桌面响应到这个Activity启动。

2.2 游戏部分

一般游戏的主 Activity 启动后,还会做一些比较耗时的事情,这时候你看到的界面是不能操作的,比如:加载游戏数据、联网更新数据、读取和更新配置文件、游戏引擎初始化等操作。从游戏开发的角度来看,到了真正用户能操作的界面才算是一个游戏真正加载完成的时间。
那么这个时间,就得使用 Log 来记录了,因为加载游戏数据、联网更新数据、读取和更新配置文件、游戏引擎初始化这些操作,都是游戏自己的逻辑,与系统无关,所以得由游戏自己定义加载完成的点。

对于游戏的启动时间,我们更倾向于计算从点击桌面图标到用户可以与游戏进行交互这个时间段作为一个游戏的启动时间。

3 总结

计算机最让人着迷的一点就是其准确性,1+1 永远等于 2,启动耗时多久就是多久,每一次可能不一样,但每一次的时间都是这一次的准确时间。

不过每个公司由于对应用的定位不同,所以对应用启动的要求也不一样。比如有的做 ROM 的公司,其内置应用的启动时间一定是要非常快的,这样给用户的第一感觉就是快、流畅;互联网公司的 App 则不是很关心启动速度,大部分互联网公司的应用都有一个启动页,用来展示广告或者功能介绍之类的,然后才会进入到主界面。需求不一样,这么做也无可厚非,不过从消费者的角度来看,越早见到主界面当然越好。

所以在做一个 Android App 的时候,一定要记得将应用的启动时间作为一个性能指标,毕竟:

天下武功,唯快不破!

转摘:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2016/0105/3830.html

原始链接: http://androidperformance.com/2015/12/31/How-to-calculation-android-app-lunch-time.html  

免责声明:文章转载自《Android 中如何计算 App 的启动时间?》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Django中CSS加载background url('')问题域知识深入学习二:建立AD DS域下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Sql 时间日期函数(转)

Sql 时间日期函数 2008年05月25日 星期日 16:29 --1. 当前系统日期、时间     select getdate() --2. dateadd 在向指定日期加上一段时间的基础上,返回新的 datetime 值    --例如:向日期加上2天    select dateadd(day,2,'2004-10-15') --返回:20...

SQL Server数据库(时间戳timestamp)类型 (转载)

timestamp介绍 公开数据库中自动生成的唯一二进制数字的数据类型。 timestamp 通常用作给表行加版本戳的机制。 存储大小为 8 个字节。 不可为空的 timestamp 列在语义上等价于 binary(8) 列。可为空的 timestamp 列在语义上等价于 varbinary(8) 列。这将导致在C#程序中获取到的timestamp类...

SpringCloud认识五之分布式锁和分布式事务

SpringCloud认识五之分布式锁和分布式事务 https://blog.csdn.net/weixin_41446894/article/details/86260854 本人讲述的是基于 Spring Cloud 的分布式架构,那么也带来了线程安全问题,比如一个商城系统,下单过程可能由不同的微服务协作完成,在高并发的情况下如果不加锁就会有问题,而传...

Android 开机问题知多少

极力推荐文章:欢迎收藏Android 干货分享 阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容: 一、 如何抓取开机问题Log 二、开机问题Log 分析流程 三、 kernel Log 搜索关键字fs_mgr 初步分析定位 四、uart lo...

python知识

ISO格式时间  包含百度联盟的广告页面都会有Hm_lpvt_xxxx以及Hm_lvt_xxx这类cookie;其具体含义和用途对于联盟使用者或许根本就不需要知道。 Hm_lpvt_xxxxxxx 为当前时间戳(秒) Hm_lvt_xxx 为一串时间戳。最近的一次访问时间戳追加在后面,最多保留4个时间戳。可以通过关闭浏览器然后再访问相同页面查看其cook...

Monkey APP压力稳定性测试

一、monkey 的使用场景   Monkey 测试是 Android 平台自动化测试的一种手段,通过Monkey程序模拟用户触摸屏幕、滑动Trackball(轨迹球)、按键等操作来对设备上的程序进行压力测试,检测程序多久的时间会发生异常 用来做什么的 压力稳定性测试 做自动化测试 Monkey 主要用于Android 的压力测试 自动的一个压力测试小工...