2021Android App开发工作必知必会之性能优化
Posted 斯音
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021Android App开发工作必知必会之性能优化相关的知识,希望对你有一定的参考价值。
android App 启动优化全记录
一、应用启动概述
1、应用启动的一般流程
应用的启动,从桌面点击应用图标到主界面用户可操作,大致遵循下面的流程:
可以看到应用启动过程中,最重要的两个进程就是 SystemServer 和 App Process . 其职责划分如下:
SystemServer 负责应用的启动流程调度、进程的创建和管理、窗口的创建和管理(StartingWindow 和 AppWindow) 等
应用进程被 SystemServer 创建后,进行一系列的进程初始化、组件初始化(Activity、Service、ContentProvider、
Broadcast)、主界面的构建、内容填充等
2、冷启动和热启动
这里还需要引入冷启动和热启动的概念,这也是我们经常会碰到的两个概念
冷启动:当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,然后再根据启动的参数,
启动对应的进程组件,这个启动方式就是冷启动
热启动:当启动应用时,后台已有该应用的进程(例:按back键、home键,应用虽然会退出,但是该应用的进程是依然会保
留在后台,可进入任务列表查看),所以在已有进程的情况下,这种启动会从已有的进程中来启动对应的进程组件,这个方式叫热启动
3、启动速度的测量
各家应该都有自己的方案,关键在于如何定义启动结束的点,这个也是一直困扰我的一个地方,有的应用很好定义,有的应用则因
为比较复杂,无法直接衡量启动速度。像 adb 这种方法自己玩玩可以,生产环境没啥用;录屏本身就有性能损耗…
这里我建议大家学习历时1年,上百万行代码!首次揭秘手淘全链路性能优化(上)中提到的测量方法:自动化、稳定、持续集成
通过OCR提取图片中的文字信息作为关键特征。该算法的优势:1. 在于应用页面上基本都是有文字的, OCR也可以识别到图
片上的文字, 文字出现则图片加载完成, 和用户体感是一致的;2. 文字作为特征,过滤掉了很多图片特征可能带来的噪声,
减少了算法调试的工作量;另外阿里集团内有非常成熟和优秀的OCR服务——读光,文档识别率超过99.7%, 使用水滴平台
封装的OCR服务,可以快速接入和使用。最终的识别方案就是基于OCR识别来进行的
二、App 优化
1、启动窗口优化
启动窗口,也叫启动页、SplashWindow、StartingWindow 等,指的是应用启动时候的预览窗口。ios App 强制有一个启动页,用
户点击桌面 App 图标之后,系统会立即显示这个启动窗口,等 App 主页加载好之后再显示主页面。Android 也有类似的机制 (启动
窗口这个是 Android 系统提供的),但是也提供了一个接口,让应用开发者设置是否显示这个启动窗口(默认是显示),部分开发者会
把这个系统提供的启动窗口禁掉,启动自己的窗口。
但是启动自己的窗口需要的时间要比直接显示系统的启动窗口所花的时间要长,这就会导致用户在使用的时候,点击图标启动 App
的时候,有一定的延迟,表现在点击图标过了一段时间才进行窗口动画进入 App,我们要尽量避免这种情况
不要禁止系统默认的启动窗口:即不要在主题里面设置 android:windowDisablePreview 为 true
自己定制启动窗口的内容,比如将启动页主题背景设置成闪屏页图片,或者尽量使闪屏页面的主题和主页一致。可以参考知
乎、抖音的做法
合并闪屏和主页面的 Activity :微信的做法,不过由于微信设置了 android:windowDisablePreview , 且他在各个厂商的白
名单里面,一般不会被杀,冷启动的机会比较少。不过也是一个可以思考的地方
2、线程优化
线程优化主要是减少 CPU 调度带来的波动,让启动时间更稳定。如果启动过程中有太多的线程一起启动,会给 CPU 带来非常大的
压力,尤其是比较低端的机器。过多的线程同时跑会让主线程的 Sleep 和 Runnable 状态变多, 增加了应用的启动速度,优化的过
程中要注意:
控制线程数量 – 线程池
检查线程间的锁 ,防止依赖等待
使用合理的启动架构
微信内部使用的 mmkernel
阿里 Alpha
3、系统调度优化
应用启动的时候,如果主线程的工作过多,也会造成主线程过于繁忙,下面几个系统调度相关的点需要注意:
启动过程中减少系统调用,避免与 AMS、WMS 竞争锁。启动过程中本身 AMS 和 WMS 的工作就很多,且 AMS 和 WMS 很多
操作都是带锁的,如果此时 App 再有过多的 Binder 调用与 AMS、WMS 通信,SystemServer 就会出现大量的锁等待,阻塞
关键操作
启动过程中不要启动子进程,如果好几个进程同时启动,系统负担则会加倍,SystemServer 也会更繁忙
启动过程中除了 Activity 之外的组件启动要谨慎,因为四大组件的启动都是在主线程的,如果组件启动慢,占用了 Message
通道,也会影响应用的启动速度
Application 和主 Activity 的 onCreate 中异步初始化某些代码启动过程中繁忙的 cpu
启动过程中繁忙的 SystemServer
4、GC 优化
启动过程中减少 GC 的次数
避免进行大量的字符串操作,特别是序列化和反序列化
频繁创建的对象需要考虑复用
转移到 Native 实现
5、IO 优化
启动过程中负载比较高,有许多系统 IO 都在此时发生,这时候 IO 的性能下降会比较快,此时 App 中的 IO 操作会比平时更慢一
些,尤其是在性能比较差的机器上。
IO 分网络 IO 和磁盘 IO ,启动过程中不建议进行网络 IO ,对于磁盘 IO 则要细扣,邵文在高手课里面有讲到:
-
- 我们要清楚启动过程中读了什么文件、多少个字节、 Buffer 是多大,使用了多长时间、在什么线程等一系列信息
-
- 进行启动过程中的 IO 监控,微信在监控 IO 时发现有用户的 db 文件达到了 500MB
下面图中可以看到低内存的时候,启动应用主线程有较多的 IO 等待(UI Thread 这一栏,橘红色代表 IO 等待 )
- 进行启动过程中的 IO 监控,微信在监控 IO 时发现有用户的 db 文件达到了 500MB
6、资源重排
利用 Linux 的 IO 读取策略,PageCache 和 ReadAhead 机制,按照读取顺序重新排列,减少磁盘 IO 次数 。具体操作可以参考支
付宝 App 构建优化解析:通过安装包重排布优化 Android 端启动性能 这篇文章
Linux 底层文件系统中 VFS 上次 App 进程之间,存在一层 pagecache,pagecache 由内存中的物理 page 组成,其内容对应磁盘
上的 block。Pagecache 的大小是动态变化的,可以扩大,也可以在内存不足时缩小。Cache 缓存的存储设备被称为后备存储
(backing store),一个 page 通常包含多个 block,这些 block 不一定是连续的利用文件重布局结合Pagecache 机制可以减少启动过程中的真正 IO 的次数,简单的说,通过文件重布局的目的,就是将启动阶段
需要用到的文件在 APK 文件中排布在一起,尽可能的利用 pagecache 机制,用最少的磁盘 IO 次数,读取尽可能多的启动阶段需要
的文件,减少 IO 开销,从而达到提升启动性能的目的
7、类重排
类重排的实现通过 ReDex 的 Interdex 调整类在 Dex 中的排列顺序。Interdex 优化不需要去分析类引用,它只需要调整 Dex 中类
的顺序,把启动时需要加载的类按顺序放到主 dex 里,这个工作我们完全可以在编译过程中实现,而且这个优化可以提升启动速
度,优化效果从 facebook 公布的数据来看也比较可观,性价比高。具体实现可以参考 Redex 初探与 Interdex:Andorid 冷启动优
化
8、主页面布局优化
应用主界面布局优化是老生常谈了,综合起来无非就是下面两点,这个需要结合具体的界面布局去做优化,网上也有比较多的资料
可以查阅
通过减少冗余或者嵌套布局来降低视图层次结构
用 ViewStub 替代在启动过程中不需要显示的 UI 控件
使用自定义 View 替代复杂的 View 叠加
9、闲时调用
IdleHandler:当 Handler 空闲的时候才会被调用,如果返回 true, 则会一直执行,如果返回 false,执行完一次后就会被移除消息
队列。比如,我们可以将从服务器获取推送 Token 的任务放在延迟 IdleHandler 中执行,或者把一些不重要的 View 的加载放到
IdleHandler 中执行
10、类加载优化
可以在 systrace 生成的文件中看到 verifyClass 过程,因为需要校验方法的每一个指令,所以是一个比较耗时的操作。
11、App 瘦身
App 瘦身包括代码瘦身和资源瘦身,通常的做法如下:
Inspect Code :Android Studio 提供的代码审查工具,实际上是内嵌了 Lint
代码混淆
图片格式的选择:如果对图片的要求不高,可以换成 565
接入资源混淆
减少 Dex 数量
12、选择合适的启动框架
启动优化整个流程的梳理,流程的梳理,我们这里引入了一个有向无环图的概念,我们会把整个的概念梳理成有向无环图的结构,
然后会去挨个加载。右边的部分,可以看到我们其实在启动的时候,首先会去加载一些必要的启动项,必要的启动项是左边流程,
会用一个多进程的方式加载,以来有向无环图进行控制,比如说我是在非必须的时候启动加载我可以放在后面再去加载。当然在整
个有向无环图的顺序加载,其实还是会做一些进程的判断,要判断某些项目是不是要在主进程里加载,某些要在初始进程里面加载
从 Spark 的 DAGScheduler 中领悟到它的核心思想,面向阶段调度(Stage-Oriented Scheduler):把应用划分成一个个的阶段
(Stage),再把任务(Task)安排到各个阶段中去,任务的编排则是通过构建 有向无环图(DAG),把任务依赖通过图的方式梳
理得 井井有条。因为它分阶段执行,先集中资源把阶段一搞定,再齐心协力去执行阶段二,这样即能控制拥塞,又能保证时序,还
能并发执行,让设备性能尽可能得到发挥大家可以参考淘宝的全链路优化的案例:历时1年,上百万行代码!首次揭秘手淘全链路性能优化(上)
13、启动网络链路优化
问题和优化点
发送处理阶段:网络库bindService影响前x个请求,图片并发限制图片库线程排队
网络耗时:部分请求响应size大,包括 SO文件,Cache资源,图片原图大尺寸等
返回处理:个别数据网关请求json串复杂解析严重耗时(3s),且历史线程排队设计不合适
上屏阻塞:回调UI线程被阻,反映主线程卡顿严重。高端机达1s,低端机恶化达3s以上
回调阻塞:部分业务回调执行耗时,阻塞主线程或回调线程
优化
多次重复的请求,业务方务必收敛请求次数,减少非必须请求。
数据大的请求如资源文件、so文件,非启动必须统一延后或取消。
业务方回调执行阻塞主线程耗时过长整改。我们知道,肉眼可见流畅运行,需要运行60帧/秒, 意味着每帧的处理时间不超过
16ms。针对主线程执行回调超过16ms的业务方,推动主线程执行优化。
协议json串过于复杂导致解析耗时严重,网络并发线程数有限,解析耗时过长意味着请求长时间占用MTOP线程影响其他关键
请求执行。推动业务方handler注入使用自己的线程解析或简化json串。
14、预加载
Activity 打开之前就预加载数据,在 Activity 的 UI 布局初始化完成后显示预加载的数据,大大缩短启动时间。 可以参考 :https://g
ithub.com/luckybilly/PreLoader/blob/master/README-zh-CN.md
15、保活
保活,是各个应用开发者的噩梦,也是 Android 厂商关注和打击的重点。不过从启动的角度来看,如果应用进程不被杀,那么启动
自然就快了,所以保活对应用启动速度也是有极大的帮助。
当然这里说的保活,并不是建议大家用各种黑科技、相互唤醒、通知轰炸这种保活手段,而是提供真正的功能,能让用户觉得你在
后台是合理的、可以接收的。比如在后台的时候,资源能释放的都释放掉,不要一直在后台做耗电操作,该停的服务停掉,该关的
动画关掉。当然对于应用开发者来说,上面说的都太多理想化了,而且目前的手机厂商也会很暴力,应用到了后台就会处理掉,不过这毕竟是
一个方向,Google 也在规范应用后台行为和规范厂商处理应用这两方面都在做努力,Android 系统的生态,还是需要应用开发者
和 Android 厂商一起取改善。
当然保活还有一条路就是走跟厂商的合作,优化后台内存、去掉重复拉起、去掉流氓逻辑、积极响应低内存警告,做好这些话后可
以跟系统厂商联系,谈放到查杀白名单和自启动白名单的可行性
16、业务梳理
这里涉及到具体的业务,每个 App 都不一样,但是所要做的事情都是一样的,下面是邵文在高手课里面提到的:
梳理清楚启动过程中的每一个模块,哪些是一定需要的,那些是可以砍掉,那些是可以懒加载的
根据不同的业务场景决定不同的启动模式
懒加载防止集中化
必要且耗时:启动初始化,考虑用线程来初始化
必要不耗时:首页绘制
非必要但耗时:数据上报、插件初始化
非必要不耗时:不用想,这块直接去掉,在需要用的时再加载
然后按需进行加载优化
更多有关Android性能优化的分享
优化心得和实战经验
性能问题是造成App用户流失的罪魁祸首之一。App的性能问题包括崩溃、网络请求错误或超时、响应速度慢、列表滚动卡顿、流
量大、耗电等等。而导致App性能低下的原因有很多,除去设备硬件和软件的外部因素,其中大部分是开发者错误地使用线程、
锁、系统函数、编程范式、数据结构等导致的。即便是最有经验的程序员,也很难在开发时就能避免所有导致性能低下的“坑”,因
此解决性能问题的关键是在于能不能尽早地发现和定位这些“坑”。
1、移动端性能监控方案Hertz
2、Android性能优化后续
3、Android性能优化之虚拟机调优
4、Android UI 性能优化
5、性能提示
6、美团外卖Android Lint代码检查实践
7、使用Android Studio和MAT进行内存泄漏分析
8、手淘全链路性能优化
9、手Q Android缓存监控与优化实践
10、微信读书(Android)阅读引擎卡顿监控测试
响应速度
启动时间和响应时间是App带给用户的最直观的性能体验。因此,无论是何种类型的App,我们都不能忽视响应时间的测试。除了稳定性以外,对于性能纬度来说,哪个方面的性能是最重要的呢?毫无疑问,就是应用的启动速度。
1、 Android App 启动优化全记录
2、Android 中如何计算 App 的启动时间?
3、应用启动时间
4、Android 冷启动优化除了老三样还有哪些新招?
5、支付宝 App 构建优化解析:通过安装包重排布优化 Android 端启动性能
6、Redex 初探与 Interdex:Andorid 冷启动优化
流畅度
在不同层次的开发工程师手里,因为技术水平的参差不齐,即使很多手机在跑分软件性能非常高,打开应用依然存在卡顿现象。
另外,随着产品内容迭代,功能越来越复杂,UI页面也越来越丰富,也成为流畅运行的一种阻碍。综上所述,对APP进行性能优化已成为开发者该有的一种综合素质,也是开发者能够完成高质量应用程序作品的保证。
1、Android 中的卡顿丢帧原因概述 - 方法论
2、Android 中的卡顿丢帧原因概述 - 系统篇
3、Android 中的卡顿丢帧原因概述 - 应用篇
4、Android 无障碍服务导致的整机卡顿案例分析
5、显示性能指标
6、渲染速度缓慢
7、Android 流畅度检测原理简析
8、Android JankTracker 原理解析
9、App流畅度优化:利用字节码插桩实现一个快速排查高耗时方法的工具
内存
Android 低内存会导致性能问题 , 具体表现就是响应慢和卡顿 。比如启动一个应用要花比平时更长的时间 ;滑动列表会掉更多帧 ;后台的进程减少导致冷启动变多 ;手机很容易发热发烫等 。
1、 Android 中低内存对性能的影响
2、 Android OOM案例分析
3、 Android 代码内存优化建议 - Android 资源篇
4、 Android 代码内存优化建议 - Android 官方篇
5、 Android 代码内存优化建议 - Java 官方篇
6、 Android 内存优化(1) - MAT 使用入门
7、 Android 内存优化之二 - MAT使用进阶
8、 Android 内存优化之三 - 打开 MAT 中的 Bitmap 原图
9、 Android 代码内存优化建议 - OnTrimMemory 优化
10、Android LowMemoryKiller原理分析
11、Android匿名共享内存(Ashmem)原理
图形栈
Android系统中图形系统是相当复杂的,包括WindowManager,SurfaceFlinger,Open GL,GPU等模块。 其SurfaceFlinger作为负责绘制应用UI的核心,从名字可以看出其功能是将所有Surface合成工作。 不论使用什么渲染API, 所有的东西最终都是渲染到”surface”. surface代表BufferQueue的生产者端, 并且 SurfaceFlinger所消费, 这便是基本的生产者-消费者模式. Android平台所创建的Window都由surface所支持, 所有可见的surface渲染到显示设备都是通过SurfaceFlinger来完成的.
1、 LWN大作:Android display pipeline本身以及进程调度!
2、 Android 中的 Hardware Layer 详解
3、 Android硬件加速原理与实现简介
4、 Android图形系统概述
5、 Choreographer原理
6、 SurfaceFlinger启动篇
7、 SurfaceFlinger绘图篇
8、 Android应用程序UI硬件加速渲染技术简要介绍和学习计划
9、 Android应用程序UI硬件加速渲染环境初始化过程分析
10、Android应用程序UI硬件加速渲染的预加载资源地图集服务(Asset
Atlas Service)分析
11、Android应用程序UI硬件加速渲染的Display List构建过程分析
12、Android应用程序UI硬件加速渲染的Display List渲染过程分析
13、Android应用程序UI硬件加速渲染的动画执行过程分析
14、Android中的GraphicBuffer同步机制-Fence
15、Android P 图形显示系统——硬件合成HWC2
16、Android P 图形显示系统——Android VirtualDisplay解析
17、Android P 图形显示系统—— 上层Client和SurfaceFlinger的交互
18、Android P 图形显示系统—— SurfaceFlinger合成流程(一)
19、Android P 图形显示系统—— SurfaceFlinger合成流程(二)
性能优化不是更新一两个版本就可以解决的,是持续性的需求,持续集成迭代反馈。在实际的项目中,在项目刚开始的时候,由于人力和项目完成时间限制,性能优化的优先级比较低,等进入项目投入使用阶段,就需要把优先级提高,但在项目初期,在设计架构方案时,性能优化的点也需要提早考虑进去,这就体现出一个程序员的技术功底了。
如果你也想提升自己移动开发的性能优化技术,或者是正在准备移动开发岗的面试,我觉得这份笔记你必定不能错过。
以上完整学习笔记pdf全部免费分享,需要的朋友只需要点赞支持一下后,【点击这里直达免费获取方式】。
以上是关于2021Android App开发工作必知必会之性能优化的主要内容,如果未能解决你的问题,请参考以下文章
Android项目实战 | 从零开始写app(14)实现图片发布模块 | 必知必会之调用系统相机拍照相册一一解决android7 打开相机闪退奔溃问题
Android NDK——必知必会之Android Studio使用CMake构建NDK项目的背后的故事