App性能优化:启动优化篇

App性能优化:启动优化篇

本篇主要探讨App启动优化相关内容

1、启动分类
  • 冷启动
  • 热启动
  • 温启动
冷启动

1.冷启动流程图
在这里插入图片描述

热启动

最快:后台切换到前台

温启动

较快:重新执行Activity的生命周期,不会重新创建Application

冷启动相关任务

冷启动之前:

  • 启动App
  • 加载空白Window
  • 创建进程

随后任务:

  • 创建Application
  • 启动主线程
  • 创建MainActivity
  • 加载布局
  • 布置屏幕
  • 首帧绘制
优化方向:

在Application和Activity生命周期阶段,是我们能比较好干预的阶段,也是优化的重点阶段

2、启动时间的测量
  1. Adb命令的方式
    Adb shell am start -W packagename/packagename.首屏Activity
    效果图如下:
    在这里插入图片描述
    thisTime:最后一个Activity启动耗时
    totalTime:所有Activity启动耗时
    waitTime:AMS启动Activity的总耗时
手动打点

误区:OnWindowFocusChanged只是首帧时间
正解:真实数据展示的时间,列表第一条数据展示出来:

btn_start.viewTreeObserver.addOnDrawListener(object:ViewTreeObserver.OnDrawListener{
            override fun onDraw() {
                val endTime=System.currentTimeMillis()
            }
        })
3、启动优化工具的使用

一、TraceView
二、SysTrace

TraceView 工具

TraceView的特点:

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

TraceView的使用的使用:

  • Debug.startMethodTracing(“App”);
  • Debug.stopMethodTracing();
  • 生成文件的位置:以Android 9 模拟器为例,文件位于:
    mnt/sdcard/Android/data/packagename/files/App.trace
    打开.trace后,Android studio 会通过Profiler分析文件
    生成cpu调用的图形信息,左侧会显示各个线程我们选中main线程
    下面就是main线程在时间范围00.000-00.298之间的图表
  1. Call Chart
    水平轴表示函数调用(或调用方)的时间,并沿垂直轴显示其被调用者。 对系统 API 的函数调用显示为橙色,对应用自有函数的调用显示为绿色,对第三方 API(包括 Java 语言 API)的函数调用显示为蓝色。 下图展示了一个调用图表示例,并描绘了给定函数的 Self time、Children time 以及总时间的概念。
    相关函数可以右键Jump to source
    在这里插入图片描述

  2. Flame Chart
    Flame Chart 标签提供一个倒置的调用图表,其中水平轴不再代表时间线,它表示每个函数相对的执行时间。
    在这里插入图片描述

  3. Top Down
    Top Down 标签显示一个函数调用列表,在该列表中展开函数节点会显示函数调用的子函数
    在这里插入图片描述

traceview注意事项
  1. 运行时开销很大,整体都会变慢
  2. 可能会带偏优化方向
  3. traceview与cpu Profiler,老版本使用traceView,新版本就是用Profiler打开的trace文件,Profiler更加强大,同时可以做内存,网络等更多的更多的性能监控。
  4. traceView可以进行手动打点,进行更加精确的监控
  5. wall clock time和Thread Time,wall time是占用的cpu的时间,thread time是线程执行的时间,cpu时间是小于线程时间的。
  6. .trace文件默认最大是8M的大小,如果初始化任务较多,最好自定义文件大小,方便精确监控
systrace工具的使用

参考官网:systrace官方指南

  • systrace:结合android内核的数据,生成Html报告
  • API 18以上使用,推荐使用TraceCompat
  • systrace 是一段python脚本,通过终端执行命令:首先进入strace.py所在目录,mac在Users/username/Library/Android/sdk/platform-tools/systrace目录下,然后运行python命令:
    python systrace.py -b 10240 -t 5 -a 包名 -o hdperformance.html sched gfx view wm am app
    • -b:指定buffer大小
    • -t:指定时间 5s
    • -a:指定包名
    • -o:指定输出文件的名称
systrace监控启动时间

1、 在application的oncreate里面添加代码:

TraceCompat.beginSection("appOnCreate");
//初始化操作
...
TraceCompat.endSection();

在这里插入图片描述
2、通过命令行开启systrace
在这里插入图片描述
执行命令后打开app,即可监听到启动信息,会在systrace目录下生成一个*.html文件。通过浏览器打开hdperformance.html文件
在这里插入图片描述

trace.html文件分析
  1. 在左侧根据包名找到我们的进程

  2. 在左侧点击Frames下面的UI Thread

  3. 操作快捷键WSAD,放大缩小,左右移动,找到在代码中设置的tag:appOnCreate

  4. 点击tag,在点击M选中这一部分
    在这里插入图片描述

  5. 选中后可以看到cpu时间和线程时间
    在这里插入图片描述

  6. 上面可以看到CPU 各个核心的使用情况
    在这里插入图片描述

systrace特点
  1. 轻量级,开销小
  2. 直观反应cpu利用率
  3. cpu time 和wall time的区别:cputime小于wall time,我们真正需要关注的优化点在cpu time
4、优雅获取方法耗时
AspectJ 面向切面编程
  • classpath ‘com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.0’
  • implementation ‘org.aspectj:aspectjrt:1.8.+’
  • apply plugin :‘android-aspectjx’
JointPoint
  • 程序运行时候的执行点
  • 获取、设置变量
  • 类初始化
Advice
  • 一种Hook,要插入代码的位置
  • Before:PointCut之前执行
  • After:PointCut之后执行
  • Around:PointCut之前之后分别执行
AspectJ 使用实例

配置好上面的aspectj插件后,编写如下aspectj代码,即可监听application启动时候每个方法的耗时:

@Aspect
public class PerformanceAop {
    @Around("call(* packagename.ApplicationContext.**(..))")
    public void getTime(ProceedingJoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        String name = signature.getName();
        long time = System.currentTimeMillis();
        try {
            joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        Log.d("PerformanceAop", name + "__cost=" + (System.currentTimeMillis() - time));
    }
}

执行效果如下:
在这里插入图片描述

AOP的优点
  1. 无侵入性
  2. 修改方便
5、异步优化最优解-启动器

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

异步优化痛点
  1. 代码不优雅
  2. 场景不好处理(依赖关系)
  3. 维护成本高
启动器核心思想

充分利用CPU多核,自动梳理任务顺序

  1. 任务Task 化,启动逻辑抽象为Task
  2. 根据所有任务依赖关系排序生成一个有向无环图
  3. 多线程按照排序后的优先级依次执行
更优秀的延迟初始化方案-分批初始化
  1. 利用IdleHandler特性,空闲执行
启动优化其他方案
  1. 提前异步SharedPreferences,在MutilDex前
  2. 启动阶段不使用子进程
  3. 提前异步类加载(mutilDex install 之后直接开启线程,通过class.forName或者new Class)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值