0
点赞
收藏
分享

微信扫一扫

启动优化1

有点d伤 2021-09-24 阅读 67
性能优化

目录

一、冷启动定义

二、 冷启动和热启动

三、冷启动、热启动的区别

四、冷启动时间的计算

五、冷启动流程

六、冷启动的优化

七、常用优化方案

闪屏优化:

业务优化:

线程优化:

线程池数量设置:

CPU密集型任务

IO密集型任务

锁检查:

GC优化:

系统调用优化:

I/o优化

数据重排:

类重排

​资源重排:

一、冷启动定义

[图片上传失败...(image-50a13f-1575207142191)]

简而言之:冷启动是APP进程未启动时,用户启动APP到启动Activity显示的时候,需要消耗的时间。两大核心消耗时间无非就是Appliction onCreate时间消耗,以及Splash Activity渲染页面前的时间消耗。

这边需要澄清一个点是:APP安装第一次启动,和APP进程杀掉再重新启动,启动的时间是有不一样的地方的,这中间有一个MultiDex的过程(attachBaseContext中)。

google的官方文档定义的是到Launcher Activity的时间,但通常的APP中会有一个splash Activity,所以有时候,我们的冷启动定义会稍微修正下,会计算到真正和用户相关的Activiy,即splash之后的MainActivity。

我以微信为例,用户从桌面点击图标开始,会经过 4 个关键阶段...

二、 冷启动和热启动

冷启动:
在启动应用时,系统中没有该应用的进程,这时系统会创建一个新的进程分配给该应用;

热启动:
在启动应用时,系统中已有该应用的进程(例:按back键、home键,应用虽然会退出,但是该应用的进程还是保留在后台);

三、冷启动、热启动的区别

冷启动:系统没有该应用的进程,需要创建一个新的进程分配给应用,所以会先创建和初始化Application类,再创建和初始化MainActivity类(包括一系列的测量、布局、绘制),最后显示在界面上。 热启动: 从已有的进程中来启动,不会创建和初始化Application类,直接创建和初始化MainActivity类(包括一系列的测量、布局、绘制),最后显示在界面上。

四、冷启动时间的计算

API19 之后,系统会出打印日志输出启动的时间; 冷启动时间 = 应用启动(创建进程) —> 完成视图的第一次绘制(Activity内容对用户可见);

五、冷启动流程

Zygote进程中fork创建出一个新的进程; 创建和初始化Application类、创建MainActivity; inflate布局、当onCreate/onStart/onResume方法都走完; contentView的measure/layout/draw显示在界面上;

总结:
Application构造方法 –> attachBaseContext() –> onCreate() –> Activity构造方法 –> onCreate() –> 配置主题中背景等属性 –> onStart() –> onResume() –> 测量布局绘制显示在界面上。

六、冷启动的优化

减少在Application和第一个Activity的onCreate()方法的工作量; 不要让Application参与业务的操作; 不要在Application进行耗时操作; 不要以静态变量的方式在Application中保存数据; 减少布局的复杂性和深度;

七、常用优化方案

闪屏优化:

针对用户点击图标后白屏或者无反应现象:
Android系统在启动APP的时候,会将第一个启动的Activity的背景拿出先展示出来,若Activity的window背景没有设置,那默认就是白屏;若设置了透明,就会点击后看起来没有反应。
我们可以通过自定义style来解决这个问题,如下:

<style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">

<item name="android:windowBackground">@drawable/img_splash</item> </style>

[图片上传失败...(image-630713-1575207142191)]

业务优化:

梳理初始化阶段的耗时业务初始化,看看是否有耗时业务可以懒加载

[图片上传失败...(image-b2e193-1575207142191)]

线程优化:

[图片上传失败...(image-5b5130-1575207142191)]

代码块

线程池数量设置:

  • CPU密集型任务

尽量使用较小的线程池,一般为CPU核心数+1

因为CPU密集型任务使得CPU使用率很高,若开过多的线程数,只能增加上下文切换的次数,因此会带来额外的开销。

  • IO密集型任务

可以使用稍大的线程池,一般为2*CPU核心数+1

IO密集型任务CPU使用率并不高,因此可以让CPU在等待IO的时候去处理别的任务,充分利用CPU时间。

对io密集型:

在这篇如何合理地估算线程池大小?文章中发现了一个估算合理值的公式

最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目

比如平均每个线程CPU运行时间为0.5s,而线程等待时间(非CPU运行时间,比如IO)为1.5s,CPU核心数为8,那么根据上面这个公式估算得到:((0.5+1.5)/0.5)*8=32。这个公式进一步转化为:

最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1)* CPU数目

可以得出一个结论:
线程等待时间所占比例越高,需要越多线程。线程CPU时间所占比例越高,需要越少线程。
以上公式与之前的CPU和IO密集型任务设置线程数基本吻合。

锁检查:

GC优化:

系统调用优化:

[图片上传失败...(image-3fb153-1575207142191)]

I/o优化

[图片上传失败...(image-2aa7f1-1575207142191)] ​

数据重排:

[图片上传失败...(image-e3ed55-1575207142191)] ​

类重排

https://github.com/facebook/redex

[图片上传失败...(image-94e8e-1575207142191)]

​资源重排:

https://mp.weixin.qq.com/s/79tAFx6zi3JRG-ewoapIVQ

仅供内部使用,未经授权,切勿外传

暂无赞赏,鼓励一下

?

+1

举报

相关推荐

0 条评论