Android 性能优化之渲染原理

每一次面试准备都是造航母
复制代码

先来看几个概念

fps:每秒传输的帧数,FPS”也能够理解为咱们常说的“刷新率(单位为Hz)”。
hz:表明屏幕在一秒内刷新的次数,Android手机通常为60HZ,也就是一秒刷新60帧,大约16.67ms刷新一次
丢帧:原本一秒中画面须要更新 60 帧,可是若是这期间只更新了 55 帧 , 那么在用户看来就是丢帧了 , 主观感受就是卡了
tearing: 一个屏幕内的数据来自2个不一样的帧,画面会出现撕裂感
jank: 绘图速度过慢,一个帧在屏幕上连续出现2次
lag:从用户体验来讲,就是点击下去到呈现效果之间存在延迟
撕裂(screen tearing):当cpu/gpu将数据准备写入buffer(缓冲区)中,但display还没来的及显示,这时cpu/gpu把下一帧数据往buffer写,还没写完,Display开始读去buffer显示,(也就是绘图数度大于显示速度),这是就会出现显示的上半部分为下一帧数据,下半部分为上一帧数据,如图所示,这就是撕裂。 android

tearing发生的缘由是display读buffer同时,buffer被修改,那么多一个buffer是否是能解决问题,这个时候双缓冲就诞生了。面试

双缓冲机制

从性能角度出发,若是只对一块缓冲区进行读写无疑效率比较低下:一方面屏幕要从该区域去读,另外一方面显卡要等待去写.所以在实际中,其实帧缓冲区实则被划分为两部分:缓存

前缓冲区: 用来缓存要显示到屏幕的帧数据 后缓冲区: 用来缓存显卡生成的帧数据. 屏幕只能前缓冲区读取数据用于显示,显卡只能日后缓冲区写入新生成的帧数据.须要注意的是两块缓冲区并不发生实际上的数据拷贝操做,即将后缓冲区的帧数据拷贝到前缓冲区,而是在前缓冲区的帧数据已经推到屏幕上,且新的帧数据被写入到后台缓冲区后,进行指针交换操做,将原来的后缓冲区变为前缓冲区 布局

但仍是有问题,假如是backbuffer准备完成一帧数据之后就进行,那么若是此时屏幕尚未完整显示上一帧内容的话,确定是会出问题的。看来只能是等到屏幕处理完一帧数据后,才能够执行这一操做了. 当扫描完一个屏幕后,设备须要从新回到第一行以进入下一次的循环,此时有一段时间空隙,称为VerticalBlanking Interval(VBI)。你们应该能想到了,这个时间点就是咱们进行缓冲区交换的最佳时间。由于此时屏幕没有在刷新,也就避免了交换过程当中出现 screentearing的情况。VSync(垂直同步)是VerticalSynchronization的简写,它利用VBI时期出现的vertical sync pulse来保证双缓冲在最佳时间点才进行交换。 因此说V-sync这个概念并非Google独创的,它在早些年前的PC机领域就已经出现了。不过Android 4.1给它赋予了新的功用,稍后就能够看到。性能

Android显示原理

  在一个典型的显示系统中分为GPU,CPU,Display(有些言论称为显示器)三部分,Android中LayoutInflater将布局中的xml标签转换为对象,cpu通过计算将它转化为多边形(Polygons)或Texture(纹理)。gpu对多边形或者纹理进行栅格化(Rasterization)操做,栅格化后的数据写入帧缓冲区中等待显示器显示。如图:优化

安卓在4.1作的优化(Project Butter 黄油计划)

  在Android 4.1以前,界面卡顿是Android中最受诟病的一点.为了解决界面卡顿问题,Google为Android引入了Project Butter计划,即常说的黄油计划.在该项目中,Google对Android显示系统进行重构,并引入了三个相当重要的改进:
动画

VSync加强:VSync不只仅用于避免画面撕裂现象,如今它还会通知GPU在渲染下一帧以前要等待屏幕完成 逐行绘制.
Triple Buffer: 三缓冲机制
Choreographer: 用于协同nimations,input和drawing一块儿工做
spa

双缓冲意味着要使用两个缓冲区(SharedBufferStack中),其中一个称为Front Buffer,另一个称为Back Buffer。UI老是先在Back Buffer中绘制,而后再和Front Buffer交换,渲染到显示设备中,其中Display处理前Front Buffer,CPU、GPU处理Back Buffer.net

须要注意的是Android中一直存在VSync机制(有待考证),只不过早期VSync只是为了不画面撕裂(screen tearing)现象.为了更好的了解加强过的VSync和Triple Buffer,咱们先来看一下早期图像显示的过程,即VSync只用来避免画面撕裂的状况:线程

这个图中有三个元素,Display是显示屏幕,GPU和CPU负责渲染帧数据,每一个帧以方框表示,并以数字进行编号,如0、一、2等等。VSync用于指导双缓冲区的交换。以时间的顺序来看下将会发生的异常:

  1. Display显示第0帧数据,此时CPU和GPU渲染第1帧画面,并且赶在Display显示下一帧前完成。
  2. 由于渲染及时,Display在第0帧显示完成后,也就是第1个VSync后,正常显示第1帧。
  3. 因为某些缘由,好比CPU资源被占用,系统没有及时地开始处理第2帧,直到第2个VSync快来前才开始处理
  4. 第2个VSync来时,因为第2帧数据尚未准备就绪,显示的仍是第1帧。这种状况被Android开发组命名为“Jank”。
  5. 当第2帧数据准备完成后,它并不会立刻被显示,而是要等待下一个VSync。因此总的来讲,就是屏幕无缘无故地多显示了一次第1帧。缘由你们应该都看到了,就是CPU没有及时地开始着手处理第2帧的渲染工做,以至“延误军机”。

其实总结上面的这个状况之因此发生,首先的缘由就在于第二帧没有及时的绘制。那么如何使得第二帧及时被绘制呢?这就是咱们在Graphic系统中引入VSYNC的缘由,

CPU/GPU根据VSYNC信号同步处理数据,可让CPU/GPU有完整的16ms时间来处理数据,减小了jank。假如CPU/GPU的FPS(FramesPer Second)高于这个值,那么这个方案是完美的,显示效果将很好。 总结,vync同步使得CPU/GPU充分利用了16ms时间,减小jank

Triple Buffer

在双缓存的基础上,android又引入了三缓存技术。 首先来看传统的双缓冲机制,理想状况下,其工做状态以下:

在上图中,以GPU一行为例,长方形A和B分别表明两块缓冲区域,分别表明前台缓冲区和后台缓冲区.开始时A做为前台缓冲区,此时GPU会想后台缓冲区B写入帧数据;当B缓冲区准备就绪后,A,B交换,B变成前台缓冲区,A变成后台缓冲区,一切都很流程,CPU/GPU充分利用每一个16.6ms,在前一个VSync到来时开始准备数据,并在后一个VSync到来时准备好数据.但问题时,咱们没法确保CPU/GPU都能在16.6ms内可以准备好数据(l可能设备较差,或者界面你叫复杂,cpu/gpu没法在16秒内处理好数据致使交换延迟)

当CPU/GPU的处理时间超过16ms时,第一个VSync到来时,缓冲区B中的数据尚未准备好,因而只能继续显示以前A缓冲区中的内容。而B完成后,又由于缺少VSync pulse信号,它只能等待下一个signal的来临。因而在这一过程当中,有一大段时间是被浪费的。当下一个VSync出现时,CPU/GPU立刻执行操做,此时它可操做的buffer是A,相应的显示屏对应的就是B。这时看起来就是正常的。只不过因为执行时间仍然超过16ms,致使下一次应该执行的缓冲区交换又被推迟了——如此循环反复,便出现了愈来愈多的“Jank”。

很显然,第一次的Jank看起来是没有办法的,除非升级硬件配置来加快FPS。咱们关注的重点是被CPU/GPU浪费的时间段,怎么才能充分利用起来呢?Google为了解决该问题,引入的三缓冲机制,即在原来双缓冲的机制上加入了第三块缓冲区.

咱们来逐步分析下这个是否有效。首先和预料中的一致,第一次“Jank”无可厚非。不过让人欣慰的是,当第一次VSync发生后,CPU不用再等待了,它会使用第三个buffer C来进行下一帧数据的准备工做。虽然对缓冲区C的处理所需时间一样超过了16ms,但这并不影响显示屏——第2次VSync到来后,它选择buffer B进行显示;而第3次VSync时,它会接着采用C,而不是像double buffering中所看到的状况同样只能再显示一遍B了。这样子就有效地下降了jank。可是带来了lag的问题,如上图所示,A这一帧在第4个vsync来的时候才显示,若是是双缓冲,那在第三个vynsc就能够显示了。

三缓冲做用: 简单的说在2个缓存区被GPU和display占据的时候,开辟一个缓冲区给CPU用,通常来讲都是用双缓冲,须要的时候会开启3缓冲,三缓冲的好处就是使得动画更为流程,可是会致使lag,从用户体验来讲,就是点击下去到呈现效果会有延迟。因此默认不开三缓冲,只有在须要的时候自动开启 一句话总结三缓冲有效利用了等待vysnc的时间,减小了jank,可是带来了lag

总结: VSync(解决画面撕裂) 三缓冲(提高CPU/GPU利用率)

谷歌提供了这么牛逼的机制,为何你写的APP还会卡? 1.界面太复杂。 2.主线程太忙。他可能还在处理用户交互或者其余事情。

参考:
lionoggo.com/2017/09/12/…
www.jianshu.com/p/0cb06877c…
blog.csdn.net/litefish/ar…

相关文章
相关标签/搜索