Android 之理解 VSYNC 信号

UI 优化系列专题,来聊一聊 Android 渲染相关知识,主要涉及 UI 渲染背景知识如何优化 UI 渲染两部分内容。


UI 优化系列专题
  • UI 渲染背景知识

View 绘制流程之 setContentView() 到底做了什么?
View 绘制流程之 DecorView 添加至窗口的过程
深入 Activity 三部曲(3)View 绘制流程
Android 之 LayoutInflater 全面解析
关于渲染,你需要了解什么?
Android 之 Choreographer 详细分析

  • 如何优化 UI 渲染

Android 之如何优化 UI 渲染(上)
Android 之如何优化 UI 渲染(下)


优化是无止境的,Google 在 2012 年的 I/O 大会上宣布了 Project Butter 黄油计划,并且在 Android 4.1 中正式开启了这个机制。

Project Butter 主要包含两个组成部分:一个是 VSYNC,另一个是 Triple Buffering。

也正是从这时候开始,作为严重影响 Android 口碑的 UI 流畅性问题便得到了有效解决。今天我们就来聊一聊这两个组成部分的工作原理,不过在理解它们之前,需要先看下所涉及的另外两个概念:

1. 刷新率

表示屏幕在一秒内刷新画面的次数, 刷新率取决于硬件的固定参数,单位 HZ(Hz)。例如常见的 60 Hz,即每秒钟刷新 60 次。

逐行扫描

显示器并不是一次性将画面显示到屏幕上,而是从左到右边,从上到下逐行扫描显示,不过这一过程快到人眼无法察觉到变化,以 60 Hz 刷新率的屏幕为例,即 1000 / 60 ≈ 16ms。

2. 帧速率

表示 GPU 在一秒内绘制操作的帧数。例如电影采用 24 fps、Android 系统采用 60 fps,即一秒钟绘制 30 / 60 帧画面。更多内容参考《Why 60 fps》。


屏幕撕裂

现在,刷新频率和帧速率需要一起合作,才能使图形内容呈现在屏幕上,GPU 会获取图形数据进行绘制, 然后硬件负责把图像内容呈现到屏幕上,这一过程在应用程序的生命周期内一遍又一遍的发生。

不幸的是,刷新频率和帧率并不总是能够保持相对同步,如果你的帧速率实际比刷新率快,例如帧速率是 120 fps,显示器的刷新频率为 60 Hz。此时将会发生一些视觉上的问题。

由于显示器提取画面是从左到右,从上到下逐行扫描提取图像显示,这一过程需要 16ms(1000 / 60),当 GPU 利用一块内存区域写入帧数据时,从顶部开始新一帧覆盖前一帧,并立刻输出一行内容。当屏幕刷新时,它并不知道图像缓冲区的状态,因此它从 GPU 抓取的帧并不是完整的数据。也就是它有一半的前一帧和一半的当前帧,这种情况被称之为屏幕撕裂

  • 理想情况下,希望显示器在完成一帧绘制之后再从 GPU 获取到下一帧图像数据,但是由于帧率和刷新频率不一致导致显示器在绘图过程中,GPU 已经开始加载下一帧图像数据。屏幕撕裂是由于帧率和刷新频率不一致的情况导致。

解决该问题的方案是双缓冲,即 GPU 和显示器都有各自的工作缓冲区。GPU 始终将完成的一帧绘制数据写入到 Back Buffer,而显示器使用 Frame Buffer。当屏幕刷新时,Frame Buffer 并不会发生变化。Back Buffer 根据屏幕的刷新将数据 copy 到 Frame Buffer,这便是 VSYNC 的用武之地。

在 Android 4.1 之前,Android 使用双缓冲机制。怎么理解呢?一般来说,同一个 View Hierarchy 内的 View 都会共用一个 Window,也就是共用一个 Surface。

而每个 Surface 都会有一个 BufferQueue 缓存队列,但是这个队列会由 SurfaceFlinger 管理,通过匿名共享内存与 App 应用层交互。

整个流程如下:

  • 每个 Surface 对应的 BufferQueue 内部都有两个 Graphic Buffer,一个用于绘制一个用于显示。系统会把内容先到离屏缓冲区(OffScreen Buffer),在需要显示时,才把离屏缓冲区的内容通过 Swap Buffer 复制到 Front Graphic Buffer 中。

  • 这样 SurfaceFlinger 就拿到了某个 Surface 最终要显示的内容,但是同一时间我们可能会有多个 Surface。这里面可能是不同应用的 Surface,也可能是同一个应用里面类似 SurfaceView 和 TextureView,它们都会有自己单独的 Surface。

  • 这个时候 SurfaceFlinger 把所有 Surface 要显示的内容统一交给 Hardware Composer,它会根据位置、Z-Order 顺序等信息合成为最终屏幕需要显示的内容,而这个内容会交给系统的帧缓冲区 Frame Buffer 来显示(Frame Buffer 是非常底层的,可以理解为屏幕显示的抽象)。

Android 一直使用 VSYNC 来阻止屏幕撕裂,对于 Android 4.0,CPU 可能会因为在忙其他的事情,导致没来得及处理 UI 绘制。所以从 4.1 开始 VSYNC 则更进一步,VSYNC 脉冲现在用于开始下一帧的所有处理。

VSYNC 类似于时钟中断,每收到 VSYNC 中断,CPU 会立即准备 Buffer 数据,由于大部分显示设备刷新频率都是 60Hz(一秒刷新 60 次),也就是说一帧数据的准备工作都要在 16ms(1000/60≈16)内完成。

这样应用总是在 VSYNC 边界上开始绘制,而 SurfaceFlinger 总是在 VSYNC 边界上进行合成。这样便可以消除卡顿,并提升图形的视觉表现。

Triple Buffering

如果理解了双缓冲机制的原理,那就非常容易理解什么是三缓冲区了。如果只有两个 Graphic Buffer 缓存区 A 和 B,如果 CPU/GPU 绘制过程较长,超过了一个 VSYNC 信号周期,因为缓冲区 B 中的数据还没有准备完成,所以只能继续展示 A 缓冲区的内容,这样缓冲区 A 和 B 都分别被显示设备和 GPU 占用,CPU 则无法准备下一帧的数据。

如果再提供一个缓冲区,CPU、GPU 和显示设备都能使用各自的缓冲区工作,互不影响。简单来说,三缓冲机制就是在双缓冲机制基础上增加了一个 Graphic Buffer 缓冲区,这样可以最大限度利用空闲时间,带来的坏处是多使用了一个 Graphic Buffer 所占用的内存。

从图中可以看出,缓冲区 B 花费的时间太长,并且正在使用 A 来显示当前帧。不过这次,系统不是在重复的缓冲区中浪费时间,而是创建一个 C 缓冲区,并开始处理下一帧。三重缓冲降低了 jank 的进一步加剧。

三缓冲并不总是存在,通常情况下仅运行一个双缓冲区,但是当发生延迟等情况时,第三个缓冲区就会出现,以便降低延迟的加剧。对于 VSYNC 信号和 Triple Buffering 更详细的介绍,可以参考《Project Butter - How it works and What it added?》。

Android 渲染框架非常庞大,而且演进的非常快。感兴趣的朋友可以进一步阅读下面的参考资料。


扩展阅读
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,529评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,015评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,409评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,385评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,387评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,466评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,880评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,528评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,727评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,528评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,602评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,302评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,873评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,890评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,132评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,777评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,310评论 2 342