如何计算 App 的启动时间

摘要:
在第一个时间段,AMS创建ActivityRecord记录块,选择一个合理的Task,暂停当前Resume的活动,启动进程,在第二个时间段调用不带接口的活动的onCreate()等,在第三个时间段中调用带接口的活动的onCreate和onResume。ThisTime,TotalTime WaitTime是三个时间之间的关系:WaitTime为总时间消耗,包括上一个应用程序活动暂停的时间和新应用程序启动的时间;ThisTime表示一系列活动中最后一个活动的开始时间;TotalTime表示启动新应用程序所花费的时间,包括启动新进程和“活动”,但不包括在上一个应用程序Activitypause中花费的时间。

应用启动场景

事实上 Android 中一个 App 的启动时间可以准确计算的.但是要分场景.也就是说要分开游戏和应用. 大家都知道,在Android中,游戏开发和应用开发是两码事.所以我们需要分开来说.

1.1 应用启动

我们平时在写应用的时候,一般会指定一个 mainActivity ,用户在桌面上点击这个 Activity 的时候,系统会直接起这个 Activity. 我们知道 Activity 在启动的时候会走 onCreate/onStart/onResume .这几个回调函数.

许多书里讲过,当执行完 onResume 函数之后,应用就显示出来了…其实这是一种不准确的说法,因为从系统层面来看,一个 Activity 走完 onCreate/onStart/onResume 这几个生命周期之后,只是完成了应用自身的一些配置,比如 window 的一些属性的设置/ View 树的建立(只是建立,并没有显示,也就是说只是调用了 inflate 而已) . 后面 ViewRootImpl 还会调用两次performTraversals ,初始化 Egl 以及 measure/layout/draw. 等.
所以我们定义一个 Android 应用的启动时间, 肯定不能在 Activity 的回调函数上下手.而是以用户在手机屏幕上看到你在 onCreate 的 setContentView 中设置的 layout 完全显示为准,也就是我们常说的应用第一帧.

上面扯得有点远,不感兴趣的话可以不看,下面直接说方法.
题主说的 adb shell am start -w packagename/activity,是可以完全应用的启动时间的.不过也要分场景.

1.2 应用第一次启动

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

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

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

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

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

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

  • startTime记录的刚准备调用startActivityAndWait()的时间点
  • endTime记录的是startActivityAndWait()函数调用返回的时间点
  • WaitTime = startActivityAndWait()调用耗时。 

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

如何计算 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。这两种情况如下图:

如何计算 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。

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

上篇【地图投影】墨卡托投影(二)MORMOT通讯类说明(转 自己记录 原文版权归原作者)下篇

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

相关文章

基于React Native的58 APP开发实践

React Native在iOS界早就炒的火热了,随着2015年底Android端推出后,一套代码能运行于双平台上,真正拥有了Hybrid框架的所有优势。再加上Native的优秀性能,让越来越多的公司在实际项目中一探究竟。58同城APP发布模块年代久远,一直计划进行重构以适应日益苛刻的用户体验,这个需求与我们在React Native上一探究竟的意愿一碰撞...

SVN使用方法

SVN版本管理模式:http://www.cnblogs.com/newstar/archive/2011/01/04/svn.html (集中式-trunk和分散式-branches) SVN使用教程总结:http://www.cnblogs.com/armyfai/p/3985660.html (图文) SVN冲突解决:http://www.cr173...

软件开发行为规范-华为

软件开发行为规范   1 软件需求分析 2 软件项目计划 3 概要设计 4 详细设计 5 编码 6 需求管理 7 软件配置管理 8 软件质量保证 9 数据度量和分析   为了把公司已经发布的软件开发过程规范有效地运作于产品开发活动中,把各种规范“逐步形成工程师的作业规范”,特制定本软件开发行为规范,以达到过程控制的目的。 与软件开发相关的所有人员,包括各级...

macOS应用程序如果在打开时提示崩溃,该怎么解决

macOS应用程序如果在打开时提示崩溃,该怎么解决?最近一次Apple静默更新之后,Apple删除了TNT的证书,因此应用程序将在7月12日之后崩溃。目前的解决方案是自己签名。 检测软件签名是否存在 1.打开终端,输入【sudo -s】2.然后会提示你输入开机密码,你就把密码输入***,输入过程中不会显示密码,输入完成后按确认键enter3.然后再终端输入...

IOS内购支付服务器验证模式

IOS 内购支付两种模式: 内置模式 服务器模式 内置模式的流程: app从app store 获取产品信息 用户选择需要购买的产品 app发送支付请求到app store app store 处理支付请求,并返回transaction信息 app将购买的内容展示给用户 服务器模式的流程: app从服务器获取产品标识列表 app从app s...

MCI:移动持续集成在大众点评的实践

一、背景 美团是全球最大的互联网+生活服务平台,为3.2亿活跃用户和500多万的优质商户提供一个连接线上与线下的电子商务服务。秉承“帮大家吃得更好,生活更好”的使命,我们的业务覆盖了超过200个品类和2800个城区县网络,在餐饮、外卖、酒店旅游、丽人、家庭、休闲娱乐等领域具有领先的市场地位。 随着各业务的蓬勃发展,大众点评移动研发团队从当初各自为战的“小作...