Android 显示刷新机制、VSYNC和三重缓存机制


为了理解 APP 是如何进行渲染的,我们就必须了解手机硬件是如何工作的,也必须理解什么是 VSYNC。

首先,我们需要了解2个相关概念:

  • 刷新率(Refresh Rate):代表了屏幕在一秒内刷新屏幕的次数,这取决于硬件的固定参数,例如 60Hz。
  • 帧率(Frame Rate):代表了 GPU 在一秒内绘制操作的帧数,例如 30fps,60fps。

GPU 会获取图形数据进行渲染,然后硬件负责把渲染后的内容呈现到屏幕上,他们两者不停的进行协作。

如果刷新率和帧率,各自做自己的事,不相互协调工作,那么刷新频率和帧率并不总能够保持相同的节奏。如果发生帧率与刷新频率不一致的情况,就会容易出现画面撕裂(Tearing)的现象,也就是画面上下两部分显示内容发生断裂,来自不同的两帧数据发生重叠。


为了解决 Tearing 问题,Android 引入了 VSYNC 信号以及双重与三重缓存机制。

Android 黄油计划

从 Android 4.1 开始,谷歌致力于解决 Android 系统中最饱受诟病的一个问题,滑动不如 iOS 流畅。因谷歌在 4.1 版本引入了一个重大的改进—Project Butter,也即是黄油计划。

Project Butter 对 Android Display 系统进行了重构,引入了三个核心元素,即 VSYNC、Triple Buffer 和 Choreographer。Choreographer 在之前的文章《从源码分析Choreographer是如何实现VSYNC信号的请求及帧的刷新处理?(Android Q)》中已经分析过了,三重缓存机制我们后面介绍,这里我们重点讲解 VSYNC 的作用。

VSYNC(Vertical Synchronization)是一个相当古老的概念,对于游戏玩家,它有一个更加大名鼎鼎的中文名字—-垂直同步。垂直同步(vsync)指的是显卡的输出帧数和屏幕的垂直刷新率相同。在当下,垂直同步的含义我们可以理解为,使得显卡生成帧的速度和屏幕刷新的速度的保持一致。举例来说,如果屏幕的刷新率为 60Hz,那么生成帧的速度就应该被固定在 16ms。

上文中,我们已经知道了什么事画面撕裂(Tearing)现象以及它产生的原因,而 VSYNC 最重要的作用是防止出现画面撕裂。

VSYNC 信号是由屏幕(显示设备)产生的,并且以 60fps 的固定频率发送给 Android 系统,Android 系统中的 SurfaceFlinger 接收发送的 VSYNC 信号。VSYNC 信号表明可对屏幕进行刷新而不会产生撕裂。当 SurfaceFlinger 接收到 VSYNC 信号后,SurfaceFlinger 会遍历其层列表,以查找新的缓冲区。如果 SurfaceFlinger 找到新的缓冲区,SurfaceFlinger 会获取缓冲区;否则,SurfaceFlinger 会继续使用上一次获取的那个缓冲区。SurfaceFlinger 必须始终显示内容,因此它会保留一个缓冲区。如果在某个层上没有提交缓冲区,则该层会被忽略。

通常来说,帧率超过刷新频率只是一种理想的状况,在超过 60fps 的情况下,GPU 所产生的帧数据会因为等待 VSYNC 的刷新信息而被 Hold 住,这样能够保持每次刷新都有实际的新的数据可以显示。但是我们遇到更多的情况是帧率小于刷新频率。

在这种情况下,某些帧显示的画面内容就会与上一帧的画面相同。糟糕的事情是,帧率从超过 60fps 突然掉到 60fps 以下,这样就会发生 LAG,JANK,HITCHING 等卡顿掉帧的不顺滑的情况。这也是用户感受不好的原因所在。

接下来,我们以具体示例来看 VSYNC 的作用。

没有使用 VSYNC 时

我们来看没有 VSYNC 的情况:

这个图中有三个元素,Display 是显示屏幕,GPU 和 CPU 负责渲染帧数据,每个帧以方框表示,并以数字进行编号,如0、1、2等等。

  1. CPU 正常执行帧1,GPU 正常渲染帧1,所以帧1正常显示。
  2. 但,CPU 由于被占用等原因,等到即将显示帧2时,它才开始处理第二帧的内容,这显然完不成了,所以等到第二帧显示的时候,只能使用上一帧的内容显示了,也即是丢帧了。

上面丢帧的原因,我们可以从图中看出,是因为新的一帧开始的时候,CPU 在处理其他任务,并没有马上执行下一帧的任务,那么如何让 CPU 在新的一帧开始的时候立即处理显示内容呢?答案就在 VSYNC 身上!

使用 VSYNC 信号

我们来看,Android 引入 VSYNC 之后的帧执行示意图:

  1. 第0帧显示时,CPU 和 GPU 准备好了第一帧的内容。
  2. 第1帧刚开始显示时,CPU 放下手中的任务,立马处理第2帧显示相关的任务(这里使用了消息屏障机制,可以参考前文《Android消息循环的同步屏障机制及UI渲染性能的提升(Android Q)》),这样,在第二帧显示之前, CPU 和 GPU 也提前完成了显示任务的处理,第二帧正常显示。

可以看到,使用 VSYNC 信号机制,提升了渲染任务的优先级,优化了渲染性能,可有效的减少了丢帧、卡顿等问题。

但是上图中仍然存在一个问题:CPU 和 GPU 处理数据的速度似乎都能在 16ms 内完成,而且还有时间空余,也就是说,CPU 和 GPU 的帧率要高于 Display 的帧率。由于 CPU/GPU 只在收到 VSYNC 时才开始数据处理,故它们的帧率被拉低到与 Display 相同。但这种处理并没有什么问题,因为 Android 设备的 Display FPS 一般是 60,其对应的显示效果非常平滑。

但如果 CPU/GPU 的帧率小于 Display 的帧率,情况又不同了,将会发生如下图的情况:

在第二个 16ms 时间段,Display 本应显示 B 帧,但却因为 GPU 还在处理 B 帧,导致 A 帧被重复显示。
同理,在第二个 16ms 时间段内,CPU 无所事事,因为 A Buffer 被 Display 在使用。B Buffer 被 GPU 在使用。注意,一旦过了 VSYNC 时间点,CPU 就不能被触发以处理绘制工作了。

以上是使用双重缓存机制时产生的问题,那么又如何来解决呢?

为了解决这个问题,Android 引入了 Triple Buffer 机制。

三重缓存机制(Triple Buffer)

一般我们在绘制 UI 的时候,都会采用一种称为“双缓存”的技术(例如,上面几个例子)。双缓存意味着要使用两个缓存区,其中一个称为 Front Buffer,另外一个称为 Back Buffer。UI 总是先在 Back Buffer 中绘制,然后再和 Front Buffer 交换,渲染到显示设备中。理想情况下,这样一个刷新会在 16ms 内完成,下图就是描述的这样一个刷新过程:Display 处理前 Front Buffer,CPU、GPU 处理 Back Buffer。

只有两个 Buffer(Android 4.1之前)时,CPU 在空闲时,如果 Back Buffer 被占用了,它也只能等待 GPU 使用之后再次进行写入。我们可以想想,如果有第三个 Buffer 的存在,CPU 是不是就可以提前工作,而不至于空闲了?所以,Google 在 Android4.1 以后,引入了三重缓存机制:Tripple Buffer。Tripple Buffer 利用 CPU/GPU 的空闲等待时间提前准备好数据,并不一定会使用。

引入 Triple Buffer 效果如下图所示:

上图中,第二个 16ms 时间段,CPU 使用 C Buffer 绘图。虽然还是会多显示 A 帧一次,但后续显示就比较顺畅了。

那么,是不是 Buffer 越多越好呢?回答是否定的。由上图可知,在第二个时间段内,CPU 绘制的第 C 帧数据要到第四个 16ms 才能显示,这比双 Buffer 情况多了 16ms 延迟,并且大量的缓存数据也会导致内存增大,以及显示数据是否失效等问题。所以,Buffer 三个足矣。

总结


  1. 刷新率(Refresh Rate):代表了屏幕在一秒内刷新屏幕的次数,这取决于硬件的固定参数,例如 60Hz。

  2. 帧率(Frame Rate):代表了 GPU 在一秒内绘制操作的帧数,例如 30fps,60fps。

  3. GPU 会获取图形数据进行渲染,然后硬件负责把渲染后的内容呈现到屏幕上,他们两者不停的进行协作。

  4. 如果刷新率和帧率,各自做自己的事,不相互协调工作,那么刷新频率和帧率并不总能够保持相同的节奏。如果发生帧率与刷新频率不一致的情况,就会容易出现画面撕裂(Tearing)的现象。

  5. 从 Android 4.1 开始,谷歌在黄油计划中,引入了了三个核心元素,即 VSYNC、Triple Buffer 和 Choreographer。

  6. VSYNC 信号是由屏幕(显示设备)产生的,并且以 60fps 的固定频率发送给 Android 系统,Android 系统中的 SurfaceFlinger 接收发送的 VSYNC 信号。VSYNC 信号表明可对屏幕进行刷新而不会产生撕裂。

  7. 使用 VSYNC 信号机制,提升了渲染任务的优先级,优化了渲染性能,可有效的减少了丢帧、卡顿等问题。

  8. 三重缓存机制(Triple Buffer) 利用 CPU/GPU 的空闲等待时间提前准备好数据,有效的提升了渲染性能。


**PS:更多精彩内容,请查看 --> 《Android 性能优化》
**PS:更多精彩内容,请查看 --> 《Android 性能优化》
**PS:更多精彩内容,请查看 --> 《Android 性能优化》

Android 显示刷新机制、VSYNC和三重缓存机制相关推荐

  1. Android 显示 一、 Vsync

    Android 显示系统:Vsync机制 典型的显示系统中,一般包括CPU.GPU.Display三个部分, CPU负责计算帧数据, GPU对计算好的图形数据进行渲染,渲染好后放在buffer(图像缓 ...

  2. 清除浏览器缓存之后为什么还是显示旧的html页面_H5缓存机制浅析-移动端Web加载性能优化...

    1 H5缓存机制介绍 H5,即HTML5,是新一代的HTML标准,加入很多新的特性.离线存储(也可称为缓存机制)是其中一个非常重要的特性.H5引入的离线存储,这意味着 web 应用可进行缓存,并可在没 ...

  3. android vsync,Android 显示系统:Vsync机制

    一.Vsync简介: 屏幕的刷新过程是每一行从左到右(行刷新,水平刷新,Horizontal Scanning),从上到下(屏幕刷新,垂直刷新,Vertical Scanning).当整个屏幕刷新完毕 ...

  4. 【总结】Android的16ms和垂直同步以及三重缓存

    前言 手机屏幕是由许多的像素点组成的,每个像素点通过显示不同的颜色最终屏幕呈现各种各样的图像.手机系统的类型和手机硬件的不同导致UI的流畅性体验个不一致. 屏幕展示的颜色数据 在GPU中有一块缓冲区叫 ...

  5. VSYNC+三重缓存机制+Choreographer

    从 Android 4.1 开始,谷歌在黄油计划中,引入了了三个核心元素,即 VSYNC.Triple Buffer 和 Choreographer. 在一个典型的显示系统中,一般包括CPU.GPU. ...

  6. Android的16ms和垂直同步以及三重缓存

    前言 手机屏幕是由许多的像素点组成的,每个像素点通过显示不同的颜色最终屏幕呈现各种各样的图像.手机系统的类型和手机硬件的不同导致UI的流畅性体验个不一致. 屏幕展示的颜色数据 在GPU中有一块缓冲区叫 ...

  7. android webView的缓存机制和资源预加载

    android 原生使用WebView嵌入H5页面 Hybrid开发 一.性能问题 android webview 里H5加载速度慢 网络流量大 1.H5页面加载速度慢 渲染速度慢 js解析效率 js ...

  8. H5缓存机制浅析-移动端Web加载性能优化

    1 H5缓存机制介绍 H5,即HTML5,是新一代的HTML标准,加入很多新的特性.离线存储(也可称为缓存机制)是其中一个非常重要的特性.H5引入的离线存储,这意味着 web 应用可进行缓存,并可在没 ...

  9. H5缓存机制浅析-移动端Web加载性能优化【干货】

    转载:H5缓存机制浅析-移动端Web加载性能优化[干货] 作者:贺辉超,腾讯游戏平台与社区产品部 高级工程师 目录 1 H5缓存机制介绍 2 H5缓存机制原理分析 2.1 浏览器缓存机制 2.2 Do ...

最新文章

  1. ssl 接收到一个超出最大准许长度的记录_我所经历的一次Dubbo服务雪崩,这是一个漫长的故事...
  2. 双十一秒杀架构模型设计实践!
  3. ubuntun_11.04安装
  4. 用JavaScript实现简单的excel列转sql字符串
  5. 事件标志组的原理与创建
  6. 前端学习(3348):数组方法的运用和数值
  7. elementUI弹框form多元素表单问题 - 抛砖篇
  8. 华为matebook和linux版本区别,华为MateBook14Linux版本开箱评测 | 从来没有让我们失望!...
  9. mysql最长字段_在mysql中使用GROUP BY时,如何选择最长的文本字段?
  10. 【图像去噪】基于matlab GUI均值+中值+高通低通+巴特沃斯+PCA+小波+维纳滤波图像去噪【含Matlab源码 1705期】
  11. educoder JAVA实训答案
  12. 前端css实现气泡框
  13. MySQL分库分表总结及面试案例
  14. 深大uooc学术道德与学术规范教育第二章
  15. 苹果手机删除的视频怎么找回
  16. es6---Promise
  17. 016-JLE JNG(小于等于)
  18. 发现答案茶,真的不一样
  19. 线性判别函数(Python实现批感知器算法、Ho Kashyap算法和MSE多类扩展方法)——模式识别编程作业
  20. swiper 轮播图,最后一张图与第一张图无缝衔接

热门文章

  1. findbugs 接口文档_Findbugs安装使用文档
  2. (人、机、料、法、环)搞不懂,你还能做生产?
  3. 《OpenCV》配置多个C++版本的opencv(Ubuntu18.04)
  4. 关于火炬之光Demo设计的视频课程
  5. 码农吃饭的家伙电池充不了电了-拯救ThinkPadT470电池
  6. ImageLoader 内存溢出OOM 手动清理缓存
  7. 美图上线AI开放平台,服务AR试妆、广告营销、智能硬件等行业
  8. RDBMS(关系型数据库管理系统)和 OODBMS(面向对象数据库管理系统)区别
  9. Spring框架实现原理
  10. 【优化算法】基于树种优化算法求解单目标优化问题附matlab代码