应用启动慢、使用过程中速度变慢、页面卡顿、帧率降低……这些问题直接关系到用户体验。如何优化应用性能?在优化过程中需要注意哪些细节?评价应用性能又有哪些维度和标准?华为技术专家姚鑫将为你解读“安卓绿色联盟”性能标准,同时教你如何进行应用性能优化。
安卓绿色联盟性能标准从四个维度评价应用的性能:
首先是主观的体验指标,比如应用的启用时间、应用滑动的帧率;
第二点评估应用对系统资源的消耗,包括内存及CPU占用;
第三点应用设计是否符合高性能的要求,评估应用会不会过度绘制及内存泄露;
第四点应用是否遵守安卓StrictMode(严苛模式);
(1)应用启用速度
应用启动速度分为两个指标:
①应用冷启动时间。冷启动即手机开机后,首次打开应用启动所消耗的时间;后台应用被系统内存回收机制清理后,再次打开应用,也等同于冷启动。
②应用热启动时间。应用使用后未关闭而是切到后台,此时应用再次打开就是热启动。
(2)界面显示帧率
很多应用显示界面都是立式显示,常见的微信聊天、微博、新闻客户端等都是上下滚动显示的,用户眼睛所看到的流畅度就可以反应应用性能,流畅度是用显示帧率衡量的。
安卓手机是依据LCD硬件刷新周期进行显示的,大部分手机都是以60HZ/s进行刷新的,所以帧率的高低明显影响了用户的应用体验。如果一个应用显示帧率稳定在55帧以上,用户会感到画面流畅,如果帧率突然由50掉到40又升到50帧,这时应用界面看上去就会一直跳动,出现卡顿。
所以说,应用启用速度和界面显示帧率是衡量应用性能最直观的指标。因此,安卓绿色联盟性能标准的一个重要指标就是主观体验指标。
资源消耗分为两部分,一个是内存的占用,一个是CPU的占用。应用性能表现好坏,也要看它对整个系统的影响。比如一个应用在前台用户使用过程中表现非常好,当把它切到后台时,就发生了CPU占用较多或内存泄露等情况,会影响用户正在使用的前台其他应用。
(1)内存占用
这个指标涉及到应用在前台打开之后占用内存的多少,如果前台内存占用过高,会触发系统内存回收机制,导致其他正在后台的应用被清理,极端情况下,会引起前台依赖的后台应用被清理,导致前台功能异常。
(2)CPU占用
应用被切到后台占用CPU过多,会导致两种情况:
①前台正使用应用得不到调度,发生卡顿;
②整个手机功耗升高,进而带来发热问题
对于应用质量,划定了以下几个指标:
(1)过度绘制
应用的界面过于复杂,很多地方需重新绘制,会引起整个系统负担升高,表现在:
①整个硬件,比如CPU、GPU负担增大,导致功耗、发热等问题,进而影响前台应用;
②大量数据绘制本身就会导致应用在使用过程中产生卡顿问题。
(2)内存泄露
内存泄露,应用开发者一些开发资源在切换或退出时未做释放,导致内存的持续泄露。一个相关资源没有被释放,每进入一次就会创建一次、内存会累加增大。因为安卓会有一个out of memory门限,如果应用达到这个门限,系统就会强制清理。
严苛模式
严苛模式是谷歌在M版本新加的针对应用主线程动作的监控,在一些UI主线上做一些IO操作或通信阻塞行为都会被StrictMode监控出来,这些阻塞行为导致整个主线程被阻塞,引起界面停顿、刷新停顿或者是卡顿。
市场上手机拥有不同的机型,安卓版本也具有碎片化,安卓绿色联盟制定的标准会针对用户体验最佳的一个数值制定。相关标准都可以在华为OpenLab进行全方位自动化测试。
应用界面的一次显示过程需要经过应用到LCD的漫长过程,应用设计和系统状态都会导致这个过程产生延迟。
界面显示
一个应用是通过手机屏幕呈现在用户面前的,应用跟人的第一交互是视觉交互,所以界面显示十分重要。
应用的界面显示在应用端通常是把元素布局做出来,调相关的OpenGl接口去绘制应用元素布局。但实际中,应用界面的显示会与系统有非常多的交互,从开始绘制界面到手机LCD的显示是一个非常漫长的过程。在这个过程中,应用的设计有问题或者界面布局比较复杂都会导致性能变低,当前系统状态也会导致系统性能问题。
应用界面的一次显示过程需要经过应用到LCD的漫长过程:
(1)应用要绘制界面首先要通过Windows Manager做界面布局
(2)然后到安卓的ViewRoot,系统会生成一个图层,在上面画一些相关东西
(3)当应用端工作完成后,整个图中相关的东西会被传送到安卓native中间层,通过Surface Flinger,这是一个显示的核心服务:
①首先它会做界面的渲染,现有安卓基本上利用GPU硬件去渲染,只要界面不过于复杂, GPU可以在短时间内完成界面渲染;
②界面渲染完成后,通过Surface Flinger作为主控,把这个界面跟当前屏幕上其他元素进行叠加。
当打开微信界面时,界面最顶端是手机状态栏,会有信号、电量、时间,这个在安卓系统叫Statusbar;在屏幕最下方还会有返回键和Home键,这个在安卓系统叫Navigation bar;在安卓系统中,这两个bar分别是两个独立的图层,最终手机上看到的一张图就是Surface Flinger通过hwcomposer合成的;
这中间会经过应用到安卓框架到native到内核驱动最终再到硬件的过程。按照整个安卓显示机制,整个过程是通过LCD的Vintek进行驱动的,Vintek每秒绘制60HZ,平均下来一帧是16.7毫秒,所以所有的动作都要集中在16.7毫秒来完成才能确保LCD的每次刷新能够使用户看到最流畅画面。
静态性能问题
一个应用启动慢或是滑动卡顿,可能有几方面的影响:
(1)Inflate时间长
这部分是由应用或界面过于复杂或是加载东西过多导致。
(2)draw绘制时间长
这部分是由于手机提供的能力导致的,比如Render Thread渲染时间长;渲染更多体现的是CPU能力,当系统负荷很大,温度很高时,CPU降频,系统能力降低也会导致卡顿。
(3)合成执行时间过长
从目前的硬件条件看,该问题已经得到很好解决。
(4)浏览网页卡顿
浏览网页,需要实时从网上获取数据,该问题可能与网络传输限制有关。
影响从系统面来看,性能和GPU、CPU、内存、IO繁忙情况有关;从应用方面来讲,可能与UI和主线程逻辑设计有关。
StrictMode
StrictMode是安卓提供的一些机制,可以通过开发者选项进行开启。StrictMode在应用开发过程中可以识别出主线程,做一些操作。因为主线程一旦阻塞可能会导致整个界面停滞。利用StrictMode可以发现主线程做的数据库、IO操作或者复杂的算法,迅速找到界面卡顿的原因。
Overdraw debugger
Overdraw是现在做应用性能碰到最多的问题。追求界面更加漂亮,就可能带来过度绘制的问题。安卓系统可以通过开发选项调试GPU过度绘制,通过颜色来区分界面过度绘制的情况。
Profile GPU Rendering
如果界面渲染在16毫秒内完成,就可以保证比较流畅用户体验。通过Profile GPU Rendering可以纵观全局。
Trace View
这是安卓SDK里面提供的工具,可以通过下载android studio去获得它。
Systrace
Systrace是安卓提供的一个比较强大的性能分析工具,也是在分析性能最重要的手段。
Systrace文件抓取:工具启动后会设置一些过滤选项,根据实际情况而定可以选择自己需要的选项,设置好后点击“ok”,工具就开始抓取log,开始在手机上做你的操作,5s时间到log自动保存到设置的路径下;
Systrace文件分析:打开chrome浏览器地址中输入chrome://tracing,load刚才抓取的Systrace文件就可以以图形界面的方式展开,如下图所示:(http://developer.android.com/tools/debugging/systrace.html);
应用启动:
界面滑动:
①案例:界面滑动卡顿
分析:抓取界面滑动时的systrace和applog
从systrace看UI thread执行draw的时间相当耗时导致丢帧卡顿,而且大部分时间都在做decodeBitmap,共耗时99.045ms,如上图红框部分。
从applog中也可以看出有StrictMode相关的错误提示,从中可以定位到耗时函数。
StrictMode日志示例:
②案例:界面切换慢,过程掉帧
分析:抓取界面切换的applog
从systrace看到报StrictMode相关的错误提示,从中可以看到是在主线程执行了IO操作file.exists(),通过进一步分析代码发现, UI主线程中通过file.exists(),现读现解 zip 的方式load对应资源。
应用设计开发过程中避免内存泄露
内存泄露不仅会造成整个性能发生问题,也会造成整个功能的异常。
Android应用是运行在虚拟机之上的,虽然虚拟机会进行垃圾回收,但这并不意味可以忽视内存管理,更应该留意内存受限的移动设备上的内存使用情况。
常见内存泄露check方法:手动关闭try/catch/finally中使用网络文件等流文件的对象;
关注对象:
HTTP、File、ContendProvider、Bitmap、Uri、Socket
注意关闭onDestroy()或者onPause()中未及时关闭对象
防止如下内存泄露:线程泄漏、Handler泄露、广播泄露、第三方SDK/开源框架泄露、各种callBack/Listener的泄露。
开发过程多使用内存泄露检测工具进行压力测试
常见内存泄露检测工具:Memory Monitor、Allocation Tracker、Heap Viewer、LeakCanary。
避免不良设计或程序算法
运行时CPU占有率持续偏高,必然加大系统的负载,不但会引起功耗增加,还会引起后台的进程竞争CPU资源,长时间的高负载会最终导致发热降频,引起整机性能下降。
建议主要业务处理分散到不同线程,便于后续利用多核处理器的并行处理能力。
使用top命令观察应用线程的CPU占有率,找出高负载的线程进行分析
合理使用系统资源:对于系统广播,要避免同一广播在多个不同实例中重复注册;对象释放时必须保证注销广播,避免广播注册泄露;尽量不要多度依赖广播机制进行通信,只注册必要的广播;尽量不要注册使用频繁发生的系统广播;不高频调用系统服务接口,避免引起系统互锁造成阻塞;
避免OnXXX 回调函数中进行耗时操作
Android系统中正常情况下所有OnXXX函数均运行在主线程里面,因此禁止在这些函数里面直接或间接调用如下操作:Network communication;Reading or writing to a file;Creating, deleting, and updating elements in databases;Reading or writing to SharedPreferences;Image processing;Text parsing;
避免前台应用启动后台应用或服务
用户在主动交互中通常对交互的响应时间(例如从触摸到界面变化)存在一定的宽容度,而被动交互(例如启动过程的等待、媒体播放)中出现的延迟或卡顿更易引发用户的反感。此间如果涉及到多个进程启动,创建进程存在显著开销和内存压力等不可控因素。
推荐做法:需避免引发CPU、内存、IO等资源短时间内的巨大压力,造成设备流畅性的急剧下降、耗电上升,带来严重的应用启动阶段用户体验和全局设备体验的双重损害。
近期,我们会针对应用的兼容性、安全性、功耗、性能、稳定性展开详细解读,介绍测试经验。如果不想错过专家的干货分享,敬请关注“安卓绿色联盟”微信公众号,获取每周最新直播内容咨询、参与专家互动,解决技术难题。