应用启动速度优化总结

1.应用启动的三种方式
(1)冷启动
冷启动代表app从数据完全被擦除的状态启动的过程,在此之前,app所属的进程还未被创建。冷启动一般发生在系统重启后或者app被系统杀死后app首次被启动。

冷启动分为以下三个步骤:①加载并启动app;②启动后展示系统配置的空白Window;③创建app进程。

在创建完app进程后,则会进行下面几个步骤:①创建app用到的对象;②启动主线程(UI线程);③创建app的main activity;④加载activity的view;⑤布局屏幕;⑥完成首帧的绘制

(2)温启动
温启动这个名词平时不常见到,官方文档中是这样解释的:温启动包含了冷启动的一部分操作集,同时它的消耗要比冷启动要少。温启动的常见场景如下:
用户退出app后重新进入(用户点击back键退出,又重新启动)。
第一种情况,当app退出后,进程有可能仍在运行,这时候如果重新启动app,那么activity必须要从onCreate()生命周期开始重新创建。第二种情况,系统干掉了驻留内存的app。这时如果重新启动app,那么进程和activity都是需要重新创建,但onCreate() 会传入 saveInstance。通过使用saveInstance可以节省耗时。
总的来说温启动在耗时上介于冷启动和热启动之间。

(3)热启动
应用程序的热启动要比冷启动简单,消耗也更少,热启动的常见场景就是app的前后台切换。
在从后台切换到前台的过程中,如果应用程序的activities还驻留在内存中,app就不需要再重复经历对象初始化,布局加载和渲染这些步骤.
但是,如果某些内存因为内存整理(比如说onTrimMemory())而导致被清理,那么在响应热启动事件时这些被清理的对象就需要重新创建。
热启动和冷启动在屏幕表现上一致,在app完成activity的渲染之前都会一直展示空白屏幕。

2.统计应用启动时间
adb shell am start -W -S [packageName]/[ActivityPath]
-W 列出启动过程中统计到的具体数据
-S 强制停止当前的Activity,重新启动
adb shell am start -W -S com.zhihu.android/.app.ui.activity.MainActivity
Stopping: com.zhihu.android
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.zhihu.android/.app.ui.activity.MainActivity }
Status: ok
Activity: com.zhihu.android/.app.ui.activity.MainActivity
ThisTime: 1766
TotalTime: 1766
WaitTime: 1780
Complete
ThisTime与log中的ActivityManager: com.zhihu.android/.app.ui.activity.MainActivity: +1766ms时间是一致的。
WaitTime 就是总的耗时,包括前一个应用 Activity pause 的时间和新应用启动的时间;
ThisTime 表示一连串启动 Activity 的最后一个 Activity 的启动耗时;
TotalTime 表示新应用启动的耗时,包括新进程的启动和 Activity 的启动,但不包括前一个应用 Activity pause 的耗时。
也就是说,开发者一般只要关心 TotalTime 即可,这个时间才是自己应用真正启动的耗时。
总之,TotalTime是我们在开发过程中应该改关注的一个时间值,它基本上可以与应用的冷启动过程挂钩。

3.优化应用的启动时间
由于我不负责单个应用具体优化,故这段主要是摘抄自别的博客~
优化app启动实际上就是优化冷启动过程,因为冷启动过程包含了启动过程中的每一步。
优化一般分为两步:
优化进程创建过程的耗时(在应用层面就是优化Application的生命周期函数内的耗时操作)以及优化 Activity的创建过程。
优化Applicatoin.onCreate()中的耗时操作
(1).一般在Applicatoin的创建过程中,都会做一些初始化的工作,例如:Application.init()初始化操作。在这些初始化的操作中,难免会包含一些文件读写,数据库的增删改查,参数配置,等等耗时操作,优化这部分的思路是:通过延时和异步来解决。
例如Application.init() ,这种全局管理类的初始化操作有时候可以懒加载的,就是说通过单例模式结合懒加载在我们需要用到相关类的时候在进行初始化,而不是一股脑的全部放在Application.onCreate()中.
(2).通过异步的方式.具体来说就是将不是特别紧急的耗时操作放在低优先级的工作线程中来异步进行,或者在后台service中开启线程来进行.但是这样做有一个特别需要注意的地方,对于那些短耗时的操作来说,这么做其实很有可能造成负优化的效果.
因为我们的最终目的是让应用的首帧画面尽快的加载出来,用户能够迅速地进入到MainActivity当中,
但是不加考虑的将短耗时操作放入异步线程中,这些工作线程很有可能在MainActivity进行布局和渲染前就已经完成了自身使命,
那么这样来看布局初始化前的绝对时间并没有减少,相反因为建立线程和切换线程等开销,造成了更多的时间消耗,所以这是一个特别需要注意的地方。
Application的优化工作大概就这些,因为各个app复杂程度不同,业务类型不尽相同,具体的优化操作肯定会比较深入。

4.从系统方面(Frameworks)来进行优化
(1).在应用退出(按recent键上滑退出)的时候启动一个空进程,供温启动使用。
(2).缩短启动动画
对比发现,我们主要慢在启动动画这块,如果去掉动画对比,差距大幅缩小;
当前我们的应用启动动画的持续时间保持原生的private static final long APP_LAUNCH_DURATION = 450;//Launcher中
从视频来看,小米10应该是优化过的;
基本上每个应用都是动画相比过长导致的和对比机差距过大;
如果这块时间优化150~200ms, 应用启动时间就能大幅减低,基本能够达到测试要求
(3).CPU提频
在ActivityThread中执行performLaunchActivity方法时,对启动应用操作提频:

if (r.intent.hasCategory("android.intent.category.LAUNCHER")) {
    int aBoostTimeOut = 500;
    int aBoostParamVal[] = {0x40C00000, 0x1, 0x40804000, 0xFFF, 0x40804100, 0xFFF, 0x40800000, 0xFFF, 0x40800100, 0xFFF};
    mPerf = new BoostFramework();
    if(mPerf != null) {
        mPerf.perfLockAcquire(aBoostTimeOut, aBoostParamVal);
    }
}

(4).移除不需要的SystemProperties.set
移除了ActivityStarter.java#startActivity方法中不需要的SystemProperties.set("persist.xxx.xxx")。
一个SystemProperties.set("persist.xxx.xxx")平均耗时10ms左右;在单个Activity的启动中两个set耗时占用了20ms左右;
在三方应用的启动中,由于一般三方应用都会先启动SplashActivity然后再启动MainActivity,故可以优化40ms左右。
(5).除了前面三条外,系统本身没有太多优化的余地,一般是从开发人员在系统中增加的一些功能开始查看,看是否有优化的地方,以及相应的功能是否极大影响了系统的速度。

扫描二维码关注公众号,回复: 13613512 查看本文章

猜你喜欢

转载自blog.csdn.net/hanhan1016/article/details/109225320