App启动优化

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锁频(提一句,可能导致耗电量增加)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • 0 纸上谈兵——App启动优化 纸上谈兵系列是我在学习App性能优化的笔记,纸上谈兵这个名字就很好的反应了这次只是...
    nick_young阅读 1,366评论 0 2
  • anr文件路径 /data/anr/traces.txt 启动优化工具 traceview: Debug.star...
    7i昂阅读 327评论 0 0
  • 用户希望应用能够及时响应并快速加载。启动时间过长的应用可能会导致用户在对应用给出很低的评分,甚至完全弃用。 启动状...
    zcwfeng阅读 2,979评论 1 28
  • APP性能优化已成为衡量中高级Android开发程序员的标准之一,所以想要突破职业瓶颈,掌握一些必要的优化技巧就很...
    aitality阅读 524评论 0 1
  • 夜莺2517阅读 127,695评论 1 9