如果你觉得应用卡顿、不够流畅,不用怀疑,很大原因是没有在16ms完成你的工作。
就像这样:
如果你的某个 *** 作花费时间是24ms,系统在得到VSYNC信号的时候就无法进行正常渲染,这样就发生了丢帧现象。那么用户在32ms内看到的会是同一帧画面。
为了理解App是如何进行渲染的,我们必须了解手机硬件是如何工作,那么就必须理解什么是 VSYNC 。
在讲解VSYNC之前,我们需要了解两个相关的概念:
Refresh Rate:代表了屏幕在一秒内刷新屏幕的次数,这取决于硬件的固定参数,例如60Hz。
Frame Rate:代表了GPU在一秒内绘制 *** 作的帧数,例如30fps,60fps。
GPU会获取图形数据进行渲染,然后硬件负责把渲染后的内容呈现到屏幕上,他们两者不停的进行协作。
不幸的是,刷新频率和帧率并不是总能够保持相同的节奏。如果发生帧率与刷新频率不一致的情况,就会容易出现Tearing的现象(画面上下两部分显示内容发生断裂,来自不同的两帧数据发生重叠)。
其实上面说的就是Android的双缓冲机制,而双缓冲技术一直贯穿这个Android系统。因为实际上帧的数据就是保存在两个缓冲区中,A缓冲用来显示当前帧,那么B缓冲就用来缓存下一帧的数据,这样就可以做到一边显示一边处理下一帧的数据。
很好,下面我们来认真分析一下为什么会出现丢帧的情况:
Step1 当Display显示第0帧数据,此时CPU和GPU已经开始渲染第1帧画面,并将数据缓存在缓冲B中;
Step2 但是由于某些原因,就好像上面说的,CPU资源一时间被占用,导致系统处理该帧数据耗时过长或者未能及时处理该帧数据;
Step3 当VSYNC信号来时,display向B缓冲要数据,这下悲催了,因为缓冲B的数据还没准备好,B缓冲区这时候是被锁定的,display无可奈何,只能继续显示之前缓冲A的那一帧,此时缓冲A的数据也不能被清空和交换数据。这种情况被Android开发组命名为“Jank”,就是所谓的“丢帧”,也被称作“废帧”;
Step4 当第1帧数据(即缓冲B数据)准备完成后,它并不会马上被显示,而是要等待下一个VSYNC,Display刷新后,这时用户才看到画面的更新,中间这段时间的时间就白白被浪费掉了。
从上面的分析可以知道,因为缓冲B的超时,掉了链子,导致出现了丢帧的情况。因为一步的延迟,也很有可能导致后面的处理延迟,很可能造成一步慢步步慢啊。
出现上面这种情况怎么办,在Android系统里给出了这样的解决办法就是:再加入一个缓冲。这样就出现了三个缓冲,顾名思义,这里说的就是三倍缓冲。好,看下图:
当出现B缓冲超时,屏幕显示的还是缓冲A中的那一帧,因为此时缓冲A的数据还在使用,不能及时被交换,所以在下一次VSYNC信号来之前这段时间无任何作为,时间就会白白被浪费。为了避免这种时间浪费,在三倍缓冲机制中,系统这个时候会创建一个缓冲C,用来缓冲下一帧的数据。如上图所示,显示完缓冲B中那一帧后,下一帧就是显示缓冲C中的了。这样虽然还是不能避免会出现卡顿的情况,但是Android系统还是尽力去弥补这种缺陷,最终尽可能给用平滑的动效体验。
Overdraw(过度绘制)描述的是屏幕上的某个像素在同一帧的时间内被绘制了多次。在多层次的UI结构里面,如果不可见的UI也在做绘制的 *** 作,这就会导致某些像素区域被绘制了多次。这就浪费大量的CPU以及GPU资源。
1 使用HierarchyViewer来查找Activity中的布局是否过于复杂
2 打开Show GPU Overdraw的选项,观察UI上的Overdraw情况
蓝色,淡绿,淡红,深红代表了4种不同程度的Overdraw情况,我们的目标就是尽量减少红色Overdraw,看到更多的蓝色区域。
Overdraw有时候是因为你的UI布局存在大量重叠的部分,还有的时候是因为非必须的重叠背景。例如某个Activity有一个背景,然后里面的Layout又有自己的背景,同时子View又分别有自己的背景。仅仅是通过移除非必须的背景,这就能够减少大量的红色Overdraw区域,增加蓝色区域的占比。这一措施能够显著提升程序性能。
3 使用TraceView来观察CPU的执行情况,更加快捷的找到性能瓶颈
4 Profile GPU Rendering,选中On screen as bars选项
选择了这样以后,我们可以在手机画面上看到丰富的GPU绘制图形信息,分别关于StatusBar,NavBar,激活的程序Activity区域的GPU Rending信息。
中间有一根绿色的横线,代表16ms,我们需要确保每一帧花费的总时间都低于这条横线,这样才能够避免出现卡顿的问题。
>
性能优化的常用方法
主要内容包括布局优化,绘制优化,内存泄露优化,相应速度优化,ListView优化,Bitmap优化,线程优化等,下面主要给你举了其中的几个例子:
(1)布局优化
布局优化的思想很简单,就是尽量减少布局文件的层级。
如何进行优化呢?首先删除布局中无用的控件和层级,其次有选择地使用性能较低的ViewGroup,比如LinearLayout。如果布局中有的布局既可以用LinearLayout也可以用RelativeLayout,那就用LinearLayout,这是因为RelativeLayout比较复杂,他的布局过程花费更多的CPU时间。FrameLayout和LinearLayout一样都是一种简单高效的ViewGroup,因此可以考虑使用他们,但是很多时候,单纯的通过一个LinearLayout或者FrameLayout无法实现产品的效果,需要通过嵌套的方式来完成,这种情况建议采用RelativeLayout,因为ViewGroup的嵌套就相当于增加了布局的层级,同样会降低程序的性能。
布局优化的另一种手段是采用<include>标q,<merge>标签和ViewStub。<include>标签主要用于布局重用,<merge>标签一般和<include>配合使用,它可以减少布局的层级。而ViewStub则提供了按需加载功能,当需要时才将ViewStub中的布局加载到内存,这提高了程序的初始化效率。
(2)绘制方法
绘制优化是指View的onDraw方法避免执行大量的 *** 作,这主要有两方面。
首先,onDraw中不要创建新的布局对象,这是因为onDraw方法可能会被频繁调用,这样就会在一瞬间产生大量的临时对象,这不仅占用了过多的内存而且还会导致系统更加频繁的gc,降低了程序的执行效率。
另一方面,onDraw方法中不要做耗时的任务,也不能执行成千上万次循环 *** 作,尽管每次循环都很轻量级,但是大量的循环仍然十分抢占CPU的时间片,这会造成View的绘制过程不流畅。
(3)内存泄露优化
内存泄露在开发过程中是一个需要重视的问题,但是由于内存泄露问题对开发人员的经验和开发意识要求比较高,因此这是开发人员最容易犯的错误之一。内存泄露的优化分为两个方面,一方面是在开发过程中避免写出内存泄露的代码,另一方面通过一些分析工具比如MAT来找出潜在的内存泄露继而解决。
关于性能优化的建议
1避免黄健过多对象;
2不要过多使用枚举,枚举占用的内存空间比整型大一些。
3常量使用static final 来修饰。
4使用一些Android特有的数据结构,比如SpareArray和Pair等,他们都具有更好的性能。
5适当使用软引用和弱引用。
6采用内存缓存和磁盘缓存
7尽量采用静态内部类,这样可以避免潜在的内部类而导致的内存泄漏。
在日常的Android开发当中,性能优化是我们Android开发必不可少的话题。那么有什么样的难题呢?结合网上的学习资料以及实际工作经验,总结如下。
1如何保证异常感知灵敏度,我们可以通过一些第三方SDK实现异常统计;
2如何复原“案发”现场(就是我们常说复现bug),有时候用户反馈过来的问题,我们不一定能百分百复现,这是令人最头痛的地方。
3如何快速“止血”成功,这是一个非常令人头疼的问题。App都是静态开发,我们原生开发每一次都要发一个新的apk包。
通过上图先把用户-电量这一流程抽象出来,设备的耗电根本原因在于对硬件的使用,耗电越严重说明对硬件使用的越频繁。用户对app频繁使用说明了你用户黏性做的好,我们不能左右,所以我们要在app对硬件调用上做优化来达到节省电量的目的。
先看下移动设备元件耗电大户有哪些:
屏幕是耗电最大元件之一,但是用户要和app交互就要点亮屏幕,有人可能会觉得屏幕的明暗是用户自己根据喜好设定的,我们无可奈何。其实不然,在有些时候是可以通过UI的设计来减少屏幕电能消耗的。
在这之前我们先来看下目前常用手机屏幕材质:LCD和LED(OLED)。
无线网络主要是WIFI和移动运营商网络,通常情况下使用移动网络要比WIFI耗电要多一些。
这三种状态有一个转换流程:
通过上面了解网络连接过程,应该心里有了大概的优化建议。
精简后
①请求一个时,客户端提供一个分辨率大小,服务器根据分辨率把裁剪缩放后的给客户端返回。也可以使用Android端使用BitmapOption自行获取缩放的
②使用webp。
后面的章节会写一些关于电量检测分析工具的使用。
为了耗电优化干的这些活用户感知不到,但是如果不去优化,肆意使用,那用户就很容易感知到了。
一直以来安卓手机给人的感觉都是各种卡顿,尤其是开的程序比较多以后,和iPhone比较起来流畅度上会有不小的差距。实际上IPhone手机只是系统优化的很出色,对于安卓手机我们只要优化得当,也能有很流畅的用户体验。本文主要介绍的是从安卓系统优化、第三方软件优化以及设置优化几方面结合来改善提升安卓手机流畅度,下面一起来看看安卓手机用什么优化吧。
刷机重启抠电池
刷机是Android用户的一大乐趣,部分用户刷机是为了得到更好的易用性,比如小米的MIUI ROM,非常符合中国人的使用习惯,也有着足够丰富的个性化设定,是图省事的朋友刷机的好选择,不过对于追求高性能的朋友来说,MIUI的优化还有很大提升空间,人们纷纷选择了对于ROM优化更加出色的CyanogenMod作为刷机的第一选择。
CyanogenMod系列目前主打的ROM有CM 72和CM 9两个,CM 72基于Android 237,而CM 9则基于Android 404,其中CM 72已经基本成熟,完美支持的机型很多,是大部分机友刷机的第一选择,CM 9官方的ROM支持机型并不多,民间高手也都进行了各个机型的移植,官方支持的机型兼容性相当不错,而移植情况并不乐观。
CM系列ROM忠实于AOSP,在底层驱动方面做了很多努力,刷入之后就会感觉手机流畅了许多,同时也支持了更多的美化和手机自定义能力,比如我们可以对手机的震动回馈做细致的调整,包括按下震动的强度,抬起震动的强度等,让手机虚拟按键给我们更为真实的回馈,在CM ROM中,类似的设定非常多。
目前大部分的ROM都是使用CM进行定制的,还有一部分是对官方原版ROM进行修改,仅有少部分的ROM是修改的AOSP的源码,这些ROM指向都是谷歌Nexus系列的机型,比如GALAXY Nexus和Nexus S上的Codename和AOKP,就针对源码做了很多修改,让手机变得更流畅。
刷内核 效果好
仅仅刷手机的ROM是不够的,虽然多了很多自定义的功能,流畅度已经高于官方的ROM,但依旧有很大提升的空间,这时候我们就需要通过刷内核来进一步优化,刷内核所能带来的提升是相当明显的,但是对于刷内核大家还是要谨慎。
刷内核相比刷ROM,是一个很小的'工程,你的手机不必要Wipe,也就是说不用删除手机内部的数据,刷一下也就几分钟的功夫,所以刷内核的时候,大家完全可以多下几个内核,逐个进行测试,看看哪个内核更适合自己,就保留哪个内核。同时刷内核时我们要注意,内核需对应自己的手机版本,对应自己所刷的ROM,否则会造成手机无法启动的现象,如果遇到无法启动的现象,再刷其他可用内核就可以恢复。
大家会问了,说了这么半天,刷内核到底都有什么作用呢首先就是超频,大部分内核会默认提供降压超频,并拥有多种超频策略,来保证超频的情况下更省电。其次,还提供更多调整,比如内存虚拟机的大小,颜色管理等等,甚至一个内核可以包括一些新的Linux的补丁,比如最新的Linux 33所集成的CPU频率补丁等等。
事实上,一般的第三方ROM已经修改了手机的内核,达到了更流畅的目的,但ROM的制作速度远远比不上内核的调整速度,有时候一个ROM适用的内核在一天之内可能多次更新,所以我们可以尝试不同的新内核,看看他们的超频是不是能给我们带来性能上质的提升,是不是能更省电,是不是能通过颜色调整让我们看到更棒的画面等等。
精简内置应用
我相信Android用户通过不断的更换ROM和刷内核已经在流畅度上有了质的飞跃了,如果这时候你的手机已经比iPhone更流畅、更省电,那么我们就可以收手了,如果你还不满意,我们还有其他的路可选,精简内置应用,就是一个可以大幅度提升流畅度的方法。像Google的服务就是大部分人精简的对象。 Android系统和iOS与Windows Phone不同,这个系统拥有真正的后台运行能力,虽然iOS在推送方面做得很好,弥补了后台方面的不足,但是仍然无法与Android的真后台相比,但是由于Android的程序优先级并不像iOS和Windows Phone那样,为了流畅让当前界面拥有最高优先级,所以我们就要把Android手机后台不必要的进程关掉,以获得最佳的性能。
那么精简内部应用就是很好的选择,因为在我们使用过程中,有许多Android内部应用程序是不必要的,而这些程序会在我们不用的时候悄悄的后台打开,对我们的使用造成影响。在精简时,我们需要用到root文件管理器,同时需要保证手机已经开启root权限。进入system/app就可以进行精简了,我们需要把root管理器的当前权限设置成读写,并且修改需要删除的软件权限,打开软件执行 *** 作的权限,就可以对删除内置软件了,在精简前,大家需要对软件进行备份,或者备份整个ROM,如果你精简掉系统程序,可能会造成无法开机的情况,重刷ROM可以解决,所以大家最好找到该机型、该ROM的精简列表,以避免重复劳动。
其他优化
经过以上多方面的优化,我相信大家都已经得到了一个较为干净、运行流畅的Android了,不过在很多程序中,我们还是会遇到卡顿的情况,对于一个极端追求流畅度的玩家来说,这样的情况是绝对不允许发生的,因为我们还有进一步优化的空间。
刷后设置
常见设置就忽略了,下面是冷门但很有用的设置。设置完记得重启手机,速度飞快。
CM设置--显示设置--所有勾去掉
CM设置--界面--越界设置--越界效果--None
越界程度--Extra Light
CM设置--性能--压缩缓存--禁止
CM设置--性能--虚拟内存--32m
刷机后的优化设置:
1、设置--显示--亮度--自动调节(关闭),自动旋转屏幕(关闭),动画(不显示窗口动画)
2、位置和安全设置--使用GPS卫星(关闭);
3、应用程序设置--未知来源(√)
4、账户与同步设置--背景数据(关闭)
5、日期和时间设置--选择时区--GMT+08:00,中国标准时间
6、CM设置--应用程序--允许移动应用程序(√)
显示--屏幕关闭动画(关闭)
输入--振动反馈微调--振动反馈(关闭)
界面--状态栏调整--电量百分比(√)
越界效果--None
界面 - 通知栏电源控件--控制按钮--切换GPS(√),切换Wifi(√),切换亮度(√),切换声音(√),切换移动数据(√),切换蓝牙(√),切换飞行模式(√)
(感谢weiweiming的总结)
“设置”——“关于手机”——“自动系统更新”(去掉那个“勾”)
关闭相机拍照声音
用RE管理器进/system/media/audio/ui目录,把camera_clickogg这个文件改名或者直接删除
2、设置优化
开启性能模式
很多手机默认是标准模式甚至是省电模式,这对性能是有不少影响的,因此建议不是有特别需求还是调至性能模式(位置:系统设置,因不同手机而异)。
#FormatImgID_0#
关闭动画特效
Android 41增加了动画程序时长调整,我试过当关闭了动画以后会感觉反应迅速了很多(位置:设置→开发人员选项)。
#FormatImgID_1#
第三方软件更换启动器
实际上很多Android卡顿的罪魁祸首就是系统的启动器,现在一些品牌的手机启动器做得越来越炫丽,也越来越复杂,当然代价就是占用RAM和ROM更多,如果不是对这方面特别有要求,完全可以替换一些第三方的启动器。
卸载系统自带程序
现在官方系统自带很多程序,而且不能卸载,但是这些软件往往都会开机自启动,而且对系统流畅度影响比较大,但是要删除这些自带软件需要获取root权限。通用一些第三方ROM也会有自带垃圾软件问题,而大部分第三方ROM都自带root,所以这个相对好解决。
管理开机自启动项
减少开机自启动的软件,除了能节省电量之外,当然还能提升手机的反应速度,当然只要关闭一些不需要自启动的第三方软件就可以达到目的了。
以上就是关于Android丢帧分析与优化全部的内容,包括:Android丢帧分析与优化、(七) 下篇 Android 性能优化 Perfetto 详细介绍、android 性能优化有哪些办法等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)