关于 Android 系统流畅性的一些思考
最近一直想写一些关于 Android 系统流畅度的东西,因为流畅度这个东西,是消费者最直接能体验到的,再加上 Android 一直为人诟病的越用越卡顿,使得大家在提到安卓机的时候,都会有一丝阴影。这也是大部分人买手机首先会考虑 iPhone 的一个原因。
由于 Google 对 Android 持开放态度,各个手机厂商生产不同产品定位的机器,以及各个 Android 应用的质量良莠不齐,导致影响 Android 流畅度的因素非常非常多,并非大家简单的以为是系统没有优化好,很多时候你会发现,不同 SOC 但是相同的系统,体验完全就是两种。
所以我想和大家聊聊影响 Android 系统流畅性的一些原因,后续大家遇到卡顿的问题,也不会单纯把锅甩给系统,或许你卸载一个 App 就解决了呢.
我想从下面几个方面展开聊这个话题:
硬件层面
系统层面
应用层面
流畅度优化闭环
准备好了,那就开始吧,欢迎你加入讨论
1. 硬件层面
CPU
cpu 是手机硬件里面最核心的一个器件,这也是把 cpu 作为第一个来说的主要原因,cpu 之所以重要,是因为 Android 系统的运行过程中,大部分是跟 cpu 打交道,cpu 的能力强弱,直接决定了这款手机的档次。
手机 cpu 目前主要有高通、华为、三星、联发科四家在做,每家都有高中低档,高端 cpu 的排名大概是 高通>华为>三星>联发科, 具体的排名可以去这里看(仅供参考):http://www.mydrivers.com/zhuanti/tianti/01/
GPU
各个厂商提供的 SOC 里面,通常包含了 cpu 和 gpu ,所以大部分情况下,只要一说 cpu,其 gpu 也是对应确定的,比如高通骁龙845 SOC 带的 gpu 就是 Adreno 630。
gpu 的能力强弱更多的影响的是 gpu 强相关的应用和游戏,比如绝地求生-刺激战场 、 崩坏3 、极品飞车、狂野飙车等。反而王者荣耀这样的游戏更多的是吃 cpu 而不是 gpu。
Ram
随着 Android 版本的更新,以及硬件的更新换代,Android 系统对内存的需求越来越强,目前4G内存的手机基本上已经成了标配,旗舰机器没个 6G 或者 8G 你都不好意思说自己是旗舰。
内存主要影响系统行为,内存越大,系统就越可以以空间换时间:后台可以缓存更多的进程,杀进程不再那么激进;可以根据用户习惯预加载一些文件或者进程;各种虚拟机、hwui、进程的参数可以往宽松里调。反馈到用户那里,就是快。
当然如果后台进程多了又没有管住在后台跑,那么又会很耗电,有点得不偿失,这也是为什么国内的系统都会对进程管理这一块进行魔改。
UFS && EMMC
ufs 和 emmc 都是面向移动端的 flash 标准,我们最长听说的就是 emmc5.1 和 ufs 2.1 ,具体可以参考这篇文章:https://zhuanlan.zhihu.com/p/26431201
对于用户来说,ufs 和 emmc 的差异主要在文件读取速度、视频加载速度、文件拷贝等方面,总之能上ufs就别考虑 emmc。
不过有时候这个也是需要 SOC 支持的,比如高通 660,就不支持 ufs,能不买就别买吧。
屏幕分辨率
我们最常见的屏幕分辨率是 1080P,即 1920*1080. 对用户来说,屏幕分辨率除了会影响视觉感官外,还会在系统某些地方有差异,比如截图、录屏、合成等操作。越高的屏幕分辨率,在这里的耗时就越久,也越耗电。
这也是部分 2K 手机在某些场景下,把分辨率降低到 1080P 去运行的原因。比较失败的一个例子就是当年的魅族 MX4 Pro ,在硬件性能不足以支撑 2K 的情况下,强行上了 2K 屏幕,导致很多情况下,用户反馈又卡又耗电。
电池大小
电池大小决定着续航,也决定着手机设计,手机厂家往往需要在这两者之间找一个平衡,在电池技术没有突破的情况下,就算各家都有快充,还是建议用户在选购手机的时候,尽量选大容量电池的手机,比如 Oppo Find X 或者 Vivo NEX,或者华为 Mate 10.
SoC 平台
SoC的全称叫做:System-on-a-Chip,除了我们之前说的 cpu、gpu,Soc 上还有很多器件,具体可以看这篇文章:https://zhuanlan.zhihu.com/p/37634251
,这里就不展开讲了。
SoC 是整个手机最重要的部分,是一切体验的基础。现在高通、三星、MTK 给手机厂家提供的硬件就是 Soc ,以及其配套的 Android 适配系统。手机厂商拿到这个之后,在其基础上做整机的设计,系统这边会在配套的 Android 适配系统上做移植,也就是把各家系统差异化的东西移植到新系统上。
从目前的高通、三星、MTK 三家的适配系统的质量来看,高通提供的适配系统是功能最完善的,高通在 AOSP 的基础上,加上了高通自己的非常多的优化代码,并提供了完善的参数供手机厂商去配置,总的来说开发起来是很舒服的,本身系统的问题不会太多,加上高通的文档完善,支持速度快,国内那么多手机厂商都在用高通也就不足为奇了。
至于专利费,该给的要给啊。
我们经常会说,如果魅族早点用高通的 Soc,早 TM 上市了。
2. 系统层面
应用的管控策略
大部分 Android 应用开发者对国内的手机厂商恨的咬牙切齿,最大的原因就是国内系统对应用管控这一块进行了大量的魔改,除非你是 QQ 或者微信,否则灭了屏结果都一样。
国内厂商这么做,不是没有原因的,国内应用厂商的全家桶相互唤醒,已经到了一种丧心病狂的地步,牵一发而动全身,一点都不夸张。
我们遇到的很多用户反馈的整机卡顿问题,抓 Trace 和 Log 来看,都是后台有应用在乱跑,或者后台大量的进程常驻,内存根本不够,而这些普通用户根本就不知道怎么去处理。
所以国内厂商一般会在系统里面做限制,以保障用户的基础体验:
除非必须,一个应用偷偷拉起来另外一个应用的行为是不被允许的
除非必须,一个应用常驻后台是不被允许的
除非必须,一个应用在灭屏后在后台乱跑是不被允许的
除非必须,一个应用在后台长时间占用 cpu 是不被允许的
除非必须,一个应用弹窗是不被允许的
另外手机厂商会有其他的逻辑清理后台的应用,尽管你是合理存在的。
对进程的严格管控,也导致了国内系统的体验有一定的影响,首当其冲的是通知,如果一个应用没有接入这个手机厂商提供的 push sdk,那么他这辈子别想发通知给用户了,如果接入了手机厂商提供的 sdk(目前大部分应用的普遍做法),由于应用不在后台,用户点击通知要等好久才可以进入到对应的界面,毫无用户体验可言。
内存策略
手机厂商常常会根据手机的内存大小来定制各种不同的策略,比如后台应用的缓存个数、LowMemoryKiller 的阈值、杀进程模块的阈值、显示模块的缓存大小阈值、用户最常用应用的个数等。
很多低端机用户反馈卡顿,我们查看发现,内存是造成卡顿的主要元凶,在低内存的机器上,由于内存不足,系统会频繁杀后台,同时也有频繁的内存->文件,文件->内存 的操作,Trace 上很多 BlockIO,很多平时执行很快的操作,现在执行要很久,再加上部分进程被杀之后马上重启,重启之后又被杀,cpu 占用很高,此时就会很卡。
随着 Android 系统和应用的更新,只会越来越吃内存,目前4G内存是标配,明年或许 6G 才是标配了,能上 8G 尽量上 8G。
进程调度策略
进程调度策略有时候也会影响用户的流畅性,当应用的渲染链路上,有哪个环节因为某些原因,没有被调度到的时候,很大可能会造成卡顿。
调度不到在 Trace 上的表现是 Runnable,常见的调度不到的情况有:
同时运行的进程太多,cpu 这边的几个核处理的任务基本都是满的
进程优先级较低
调度器过于不灵敏,不能及时响应大任务
另外由于 cpu 引起的卡顿情况还有:
从大核心掉落到小核心上,小核心处理能力不足,会造成短暂的卡顿
触发温控或者触发低电量,此时某些系统会限制大核的使用,导致卡顿
系统锁也是造成卡顿的一大元凶,尤其是 wms 锁和 ams 锁,再加上 binder 通信,relayoutWindow 了解一下?
核心频率不足,导致函数执行时间过长导致卡顿
大核心被占用,任务又调度不到小核,导致卡顿
系统调优往往需要针对上面的情况做对应的处理,给用户一个好的用户体验。具体的调优方式,往往跟系统和 Soc 强相关,又涉及到 Kernel 和 功耗,改起来是牵一发而动全身,需要非常谨慎。
渲染线程和主线程
Android 应用的渲染链路上最重要的就是主线程和渲染线程,主线程就是应用启动时创建的 MainThread,对应的也会创建一个 RenderThread(硬件加速默认开启),我们平时比较看重的 GPU Profile 那条线,基本就包含了主线程和渲染线程的各个阶段的执行时间,从 GPU Profile ,就可以很容易看到应用的瓶颈
大部分应用的卡顿都发生在主线程和渲染线程上,比如:
较长时间的 input 事件处理
较长时间的动画事件处理,比如 ListView 的新 Item 的生成
复杂界面的 Measure、 Layout、Draw
较大 Bitmap 的频繁 upload
复杂渲染指令的执行
很多编程的不好的实现,都可以在上面几个步骤里面体现出来,这些都可以通过 Systrace 看出来。
当前应用的渲染链路上的一切优先级都应该是最高的,后台的进程不应该对其造成影响,这也是系统优化的核心要素,不过要做到这一点也是比较难的,你很难考虑到所有的情况,比如有的用户的使用环境就是很复杂,而且都是必须的,这时候就不是很好处理。
TripleBuffer
之前有提到 TripleBuffer,这个是 Project Butter 引进的,其中 Vsyncv 和 TripleBuffer 的引进使得 Android 的流畅度上了一个台阶,关于这个可以参考这篇文章 : https://niorgai.github.io/2017/03/21/Android-Draw-System/
对于用户来说这个是透明的,影响的是 GPU Profile 的展示,有时候如果有一条线超过 16 ms 的警戒线,它不一定代表着卡顿,这就是 TrileBuffer 的作用。
后续我会有文章专门讲这个,如何判断是真正的卡顿。
虚拟机 - Art 和 Dalvik
对用户来说,Art 虚拟机相比 Dalvik 虚拟机,最大的提升就是解放了应用的主线程,主线程不再频繁被 GC 线程 Stop ,相应卡顿也减少了很多。
当然 Art 带来的好处不止这一点,Art 随着几个大版本的缝缝补补,已经在很多地方远远超过了 Dalvik,有兴趣的可以自己查一下。
温控 && 低电量
之前提到,一旦触发温控或者低电量,系统会对资源做一定的限制,防止手机无限制过热或者快速关机。这限制就包括
降低 cpu、gpu 最高频率
减少可运行的 cpu 的核心数
杀掉部分后台进程
关闭部分特效
限制网络连接
总之,这些限制或多或少会对用户造成影响,最大的影响就是卡顿,这就是很多人会遇到打游戏的时候突然很卡的一个原因。
所以说选购手机的时候,除了要看 Soc,还要看散热是否做的够好,电池是否做的够大。
3. 应用层面
复杂的布局
复杂的布局往往是应用卡顿的最主要的元凶之一,复杂的布局意味着更长的 Measure、Layout、Draw ,这会拖慢主线程的执行速度
ListView、RecyclerView 的新的 Item 在初始化的时候也会有类似的问题,由于此时一般是在滑动,这时候的卡顿感会更明显,用户也更容易察觉,这个从 Trace 上也很容易看出来。
过多的业务逻辑
过多业务逻辑导致的卡顿和响应慢的问题,拿淘宝来举例子最合适不过了,每次你冷启动淘宝的时候,进入主界面马上滑动,总感觉跟吃了屎一样,点按钮点不动,滑界面滑不动,虽然最近的版本有优化,不过你找个低端 Android 机,还是原来的配方。
淘宝在启动的时候,需要动态加载很多东西,导致主界面响应很慢,很多东西要动态加载完成后才可以操作,后台还有大量的 dex2oat 操作,可以说是很忙了。
内存颠簸
频繁申请和释放内存,会导致内存颠簸,从 AS 的内存监视器可以看到这一点,短时间内内存曲线上下跳动非常频繁,这时候你需要检查一下是否代码写的有问题。
慢网络
慢网络指的是用户请求网络耗时很久,这会导致用户在某些界面等待内容需要很久,比如知乎经常会出现这种情况,在用户看来,这就是卡了。
不合理的设计
设计和性能往往不可兼得,需要从两者之间做取舍,设计师的设计往往很炫酷,互相嵌套的动画往往是程序员的噩梦,为了实现这些复杂的效果,程序员往往需要复杂的代码来实现,这对应用的渲染链路的压力是非常大的,而且在不同性能的机器上表现差异很大,高端机用户觉得这个效果棒棒哒,低端机用户卡的要骂娘。
程序员需要有这方面的知识和数据,好与设计师动之以情晓之以理。
不过用户是很挑剔的,现在的用户对性能的要求越来越高,哪怕是低端机用户,所以合适的设计应该考虑到这部分用户、或者针对低端机用户做区分。
代码实现错误
俗称 bug ,很多程序员不喜欢解决性能问题,因为这个东西解决起来,性价比很低,拿我司的程序员来说,解一个性能问题的时间,可以解决十几个界面显示的问题,还未必能真的解决。
不过由于代码实现错误引起的性能问题,必须要最高优先级解决。
4. 流畅度优化闭环
实验室监控 && 模拟用户
开发阶段就用各项数据来做监控和对比,尽量模拟用户的使用环境,尽早暴漏性能问题,早日解决。
用户流畅度数据收集
在用户使用阶段,收集性能数据,针对这些数据做分析,找出用户最多遇到的性能问题,针对性地做优化。需要注意此时不能在用户阶段手机太多的信息,否则会导致观察者效应
至于需要收集的数据,则需要根据相关度模型来做判断,卡顿发生的时候,系统的哪些指标是可能导致卡顿的原因,那么这些指标就是我们收集的数据。
另外用户的场景判断也非常重要,需要知道用户是在哪个场景出现的卡顿,一旦用户的数量到了一定的级别,这个是很容易发现问题的。
针对性地优化
大数据发现问题后,后续就是针对性地进行优化,把用户最常遇到性能问题的场景进行排序,对最常见的场景进行调研和优化。很多时候需要与应用开发厂商进行沟通,
然后需要把这些场景纳入到实验室监控环境里,做到 实验室监控 —> 模拟用户 — > 大数据收集 —> 针对性优化 —> 实验室监控补充. 这样一个闭环。
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:Gracker 来源: Android Performance
- 标签: 流畅性
- 发布时间:2020-02-11 10:07:27
- [67] Go Reflect 性能
- [67] Oracle MTS模式下 进程地址与会话信
- [67] 如何拿下简短的域名
- [61] IOS安全–浅谈关于IOS加固的几种方法
- [60] 图书馆的世界纪录
- [59] 【社会化设计】自我(self)部分――欢迎区
- [58] android 开发入门
- [56] 视觉调整-设计师 vs. 逻辑
- [49] 给自己的字体课(一)——英文字体基础
- [47] 界面设计速成