美文网首页安卓
App启动优化

App启动优化

作者: flynnny | 来源:发表于2021-03-21 00:00 被阅读0次

    1App启动优化介绍

    背景介绍

    第一体验 :八秒定律

    启动分类

    1冷启动
    耗时最多、衡量标准

    1.png

    帮助寻找优化方向

    2热启动
    最快

    后台--》前台

    3温启动
    较快

    重走LifeCycle 而不会重走Application、进程等的创建

    相关任务

    冷启动之前:
    启动APP
    加载空白Window
    创建进程
    随后任务:
    创建Application
    启动主线程
    创建MainActivity
    加载布局
    布置屏幕
    首帧绘制

    优化方向

    Application和Activity生命周期阶段

    2App启动时间测量方式

    adb命令

    adb shell am start -W packagename/packagename.首屏Activity
    
    2.png

    ThisTime:最后Activity启动耗时
    TotalTime:所有Activity启动耗时
    WaitTime:Ams启动Activity总耗时

    线下方便,不能带到线上;
    非严谨、精确

    手动打点

    启动时埋点,结束时埋点,二者差值

    3.png

    开始计时:
    在“attachBaseContext()”里调用!!
    结束计时:
    误区:onWindowFocusChanged只是首帧时间,首次绘制
    正确:真实数据展示,数据资料绘制的第一条展示。

    4.png

    精确,可带到线上,推荐使用。
    避开误区,采用第一条数据展示
    addOnDrawListener要求API16 ,替换为addPreDrawListener。

    3App启动优化工具选择

    traceview、systrace 两种方式互相补充

    1traceview

    图形的形式展示执行时间、调用栈等
    信息全面,包含所有线程
    使用方式

    //开始
    Debug.startMethodTracing("文件名1")
    //结束
    Debug.stopMethodTracing()
    生成文件在SD卡:Android/data/packagename/files/文件名1.trace
    

    traceview其实默认有一个最大限制8M,可在方法里参数指定。

    文件名1.trace 打开

    Top Down:
    函数的调用表,逐级调用

    5.png 6.png

    cpu真正花在上面的时间

    Call Chart:

    7.png

    Bottom UP 是Top Down 的反向即谁调用了我。
    另一个Flame不常用

    总结:
    运行时开销严重,整体都会变慢
    可能会带偏优化方向。
    traceview (可在代码中埋点)

    2systrace

    结合Android 内核的数据生成Html报告
    API18以上,之下推荐TraceCompat

    使用方式

    8.png

    起点:

    9.png

    结束:


    10.png

    [图片上传中...(12.png-7eb89d-1615694063053-0)]

    11.png 12.png 13.png 14.png

    总结:
    轻量级,开销小 ,埋在哪做哪,TraceView都做
    直接反映CPU利用率

    CPUtime与walltime区别:我们要优化的是CPUtime,是CPU真正花在上面的时间

    15.png

    为什么二者时间不一样:锁冲突。

    4优雅获取耗时

    常规方式

    背景:需要知道启动阶段所有方法耗时
    实现:手动埋点

    16.png 17.png

    统计每个方法耗时的话会非常丑陋,会导致强耦合。
    侵入性强
    工作量大

    *SystemClock.curretThreadMillis();就是CPU时间

    AOP(Aspect Oriented Programming)面向切面编程 介绍

    针对同一类问题的统一处理:性能问题
    无需入侵代码

    AspectJ使用

    18.png

    AOP相关知识点

    19.png 20.png 21.png 22.png 23.png

    AOP实战

    24.png 25.png

    修改一下代码:

    26.png 27.png

    我们没有在原来代码上操作,只是加入了一个类,非常优雅。

    无侵入性;
    修改方便;

    5异步优化详解

    优化技巧

    Theme 切换(首屏、闪屏):感官上的快

    drawable下创建文件:

    28.png 29.png

    异步优化实战

    核心思想:子线程分担主线程任务,并行减少时间

    主线程一个在工作,手机为多核。有的厂家只分配一个。
    使用线程池:
    启动阶段最好不做new线程操作:1粗放;2可能导致内存泄漏;3不能复用

    参考AsyncTask获取CPU数量
    private final int CPU_COUNT=Runtime.getRuntine().availableProcessors();
    private final int CORE_POOL_SIZE = Math.max(2,Math.min(CPU_COUNT-1),4);
    ExecutorService service =Executors.newFixedThreadPool(CORE_POOL_SIZE );
    
    service.submin(new Runnable(){
      @Override
      public void run(){
        //Bugly
        initBugly();
      }
    });
    service.submin(new Runnable(){
      @Override
      public void run(){
        //友盟
        initUmeng();
      }
    });
    ....
    

    *可不可以都放在一个Runnable里呢?
    可以,但是不好。如果比如new了三个线程只用了一个,等于资源浪费。

    *可不可以方法都用子线程呢?
    不可以。
    代码并不满足异步需求。此部分必须放在 主线程中。
    代码有先后顺序的,
    解决办法CountDownLatch:

    private  CountDownLatch mCountDownLatch =new CountDownLatch(1);//满足一次
    
    
    onCreate(){
    
      service.submin(new Runnable(){
        @Override
        public void run(){
          //友盟
          initUmeng();
          mCountDownLatch.countDown();//满足了一次
        }
      });
      .......
    
      //Create结束时调用
      try{
        mCountDownLatch.await();//检测条件,如果次数不够就在此等待
      }catch(InterruptedException e){
        e.printStackTrace();
      }
    }
    
    30.png

    6异步初始化最优解---启动器

    常规异步痛点

    31.png

    1代码不优雅;
    2存在依赖关系的不好处理。虽然可以像下面这样放一起:

    32.png

    3不方便统计。维护成本高。

    启动器介绍

    核心思想:充分利用CPU多核,自动梳理启动顺序。
    1代码Task化,启动逻辑抽象成Task。
    2根据所有任务依赖关系排序生成一个有向无环图。
    3多线程按照排序后的优先级依次执行。

    33.png

    启动器实战

    34.png 35.png 36.png 37.png

    APP性能优化系列-自定义启动器
    https://blog.csdn.net/augfun/article/details/109703739?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_baidulandingword-1&spm=1001.2101.3001.4242

    7更优的初始化延迟方案

    常规方案

    New Handler().postDelayed
    Feed显示之后调用

    时机不便控制
    主线程会卡,Feed卡顿,马上使用的话会发现。
    不够优雅,可维护性差

    更优方案 延迟方案

    核心思想,对延迟任务进行分批初始化

    利用IdleHandler特性,空闲执行

    38.png 39.png

    8启动优化其他方案

    优化总方针

    异步、延迟、懒加载
    技术、业务相结合

    注意事项

    wall time与Cpu time

    40.png

    监控的完善

    41.png

    收敛启动修改代码权限

    其他方案

    提前加载SharedPreferences:
    1Multidex之前加载,利用此阶段的CPU。
    2复写getApplicationContext()返回this

    启动阶段不启动子进程
    子进程会共享CPU资源,导致主进程CPU紧张
    注意启动顺序:APP onCreate 之前是ContentProvider

    类加载优化:提前异步类加载
    Class.forName()之家在类本身及其静态变量的应用类
    new 类 可以额外加载类成员变量的引用类

    其他

    启动阶段抑制GC
    CPU锁频(提一句,可能导致耗电量增加)

    相关文章

      网友评论

        本文标题:App启动优化

        本文链接:https://www.haomeiwen.com/subject/ubqqcltx.html