浏览器渲染流水线解析(二)

2. 网页动画

动画可以看做是一个连续的帧序列的组合。我们把网页的动画分成两大类 —— 一类是合成器动画,一类是非合成器动画(UC 内部也将其称为内核动画,虽然这不是 Chrome 官方的术语)。

  1. 合成器动画顾名思义,动画的每一帧都是由 Layer Compositor 生成并输出的,合成器自身驱动着整个动画的运行,在动画的过程中,不需要新的 Main Frame 输入;
  2. 内核动画,每一帧都是由 Blink 生成,都需要产生一个新的 Main Frame;

2.1 合成器动画

合成器动画又可以分为两类:

  1. 合成器本身触发并运行的,比如最常见的网页惯性滚动,包括整个网页或者某个页内可滚动元素的滚动;
  2. Blink 触发然后交由合成器运行,比如说传统的 CSS Translation 或者新的 Animation API,如果它们触发的动画经由 Blink 判断可以交由合成器运行;

Blink 触发的动画,如果是 Transform 和 Opacity 属性的动画基本上都可以由合成器运行,因为它们没有改变图层的内容。不过即使可以交由合成器运行,它们也需要产生一个新的 Main Frame 提交给合成器来触发这个动画,如果这个 Main Frame 包含了大量的图层变更,也会导致触发的瞬间卡顿,页端事先对图层结构进行优化可以避免这个问题。

2.2 非合成器动画

非合成器动画也可以分为两类:

  1. 使用 CSS Translation 或者 Animation API 创建的动画,但是无法由合成器运行;
  2. 使用 Timer 或者 RAF 由 JS 驱动的动画,比较典型的就是 Canvas/WebGL 游戏,这种动画实际上是由页端自己定义的,浏览器本身并没有对应的动画的概念,也就是说浏览器本身是不知道这个动画什么时候开始,是否正在运行,什么时候结束,这些完全是页端自己的内部逻辑;

合成器动画和非合成器动画在渲染流水线上有较大的差异,后者更复杂,流水线更长。上面四种动画的分类,按渲染流水线的复杂程度和理论性能排列(复杂程度由低到高,理论性能由高到低):

  1. 合成器本身触发并运行的动画;
  2. Blink 触发,合成器运行的动画;
  3. Blink 触发,无法由合成器运行的动画;
  4. 由 Timer/RAF 驱动的 JS 动画;

长久以来,浏览器渲染流水线的设计都主要是为了合成器动画的性能而优化,甚至在某种程度上导致内核动画性能的下降,比如说合成器的异步光栅化机制。不过这两年,随着对 WebApp 渲染性能包括 WebGL 性能的重视,并且随着主流移动设备的硬件性能持续提升,合成器动画的性能也已经基本不成问题,Chrome 的渲染流水线已经更多地针对内核动画的性能进行优化,甚至会导致在某些特定状况下合成器动画性能的下降,比方说倾向于为了维持图层树的稳定性,减少变更,而生成更多的图层。不过总的说来,目前 Chrome 的渲染流水线,在主流的移动设备上,大部分场景下,两者性能都能获得一个较好的平衡。

3. 动画性能分析基础

这里的性能分析主要是针对移动设备,以桌面处理器的性能,大部分场景下都不存在性能问题。目前移动设备的屏幕刷新率基本上都是 60hz,而浏览器跟其它应用一样,需要跟屏幕刷新保持垂直同步,也就是动画帧率的上限是 60 帧,这也是我们能够达到的最理想的结果。不过考虑浏览器本身的复杂程度,可能有很多后台任务在运行,而且操作系统本身也可能同时运行其它后台任务,并且移动平台要考虑能耗和散热,CPU/GPU 的调度策略会频繁地发生变化,要完全锁定 60 帧是非常困难的。

如果上限超过 60 帧,实际平均帧率超过 60 反而不难,但是如果上限是 60 帧,垂直同步下要锁定 60 帧是非常困难的,要求每一帧的各个环节耗时都要保持非常稳定。

一般而言:

  1. 帧率在 55 ~ 60 之间已经可以认为是非常优秀的水平,这时用户几乎感觉不到卡顿;
  2. 帧率在 50 ~ 55 之间可以认为是良好的水平,用户感觉到轻微卡顿,但整体来说还是比较流畅;

要达到 50 帧以上的水平,我们就需要对动画在渲染流水线的每个重要环节进行性能计算,需要知道这些环节最长允许的耗时上限和网页影响这些环节耗时的主要原因,虽然实际上很难完全锁定 60 帧,但是一般来说性能分析/优化还是会以 60 帧为目标来倒推各个环节的最大耗时。

如果是场景比较复杂的 Canvas/WebGL 游戏,以 30 帧为目标帧率是一个合理的诉求。

3.1 光栅化机制

在对动画性能进行分析之前,需要先说明一下目前的 Chrome 的光栅化机制。合成器会监控是否需要安排新的光栅化任务,当需要光栅化调度时:

  1. 合成器找到所有在当前可见区域的图层;
  2. 合成器找到这些图层在当前可见区域的分块;
  3. 合成器检查这些分块是否需要光栅化,如果需要,生成一个对应的光栅化任务并分配所需要的 Resource 放入任务队列里面;
  4. Renderer 进程会预先创建一个或者多个 Worker 线程(移动平台一般是两个),这些线程会从任务队列里面顺序取出每一个光栅化任务并运行;
  5. 光栅化任务运行后,会通知合成器,合成器根据需要检查哪些任务已经完成,已经完成的任务, Resource 会转交给对应的分块;

实际的光栅化区域会比当前可见区域要更大一些,一般是增加一个分块大小单位,对不可见区域的预光栅化有助于提升合成器动画的性能和减少出现空白的几率。

从上可知,合成器的光栅化调度完全是异步的,合成器在 Compositor 线程需要执行的就是安排光栅化任务和检查哪些任务已经完成,Compositor 线程本身不会被真正运行光栅化任务的 Worker 线程所阻塞。

时间: 2024-10-07 14:16:37

浏览器渲染流水线解析(二)的相关文章

浏览器渲染流水线解析与网页动画性能优化

若干年前,我写过一篇介绍浏览器渲染流水线的文章 - How Rendering Work (in WebKit and Blink),这篇文章,一来部分内容已经过时,二来缺少一个全局视角来对流水线整体进行分析,所以打算重新写一篇新的文章,从一个更高抽象层次和高度简化的方式对浏览器的渲染流水线进行解析,能让大部分页端同学都能够看的明白,并以此作为指引来分析和优化页面的渲染/动画性能. 有些基本概念如图层,分块,光栅化基本没有发生变化,如果读者不理解的话请参考 How Rendering Work

浏览器渲染流水线解析(一)

若干年前,我写过一篇介绍浏览器渲染流水线的文章 - How Rendering Work (in WebKit and Blink),这篇文章,一来部分内容已经过时,二来缺少一个全局视角来对流水线整体进行分析,所以打算重新写一篇新的文章,从一个更高抽象层次和高度简化的方式对浏览器的渲染流水线进行解析,能让大部分页端同学都能够看的明白,并以此作为指引来分析和优化页面的渲染/动画性能. 有些基本概念如图层,分块,光栅化基本没有发生变化,如果读者不理解的话请参考 How Rendering Work

浏览器渲染流水线解析(四)

5 非合成器动画性能分析和优化指南 前面已经我们已经把非合成器动画区分为 Blink 触发,无法由合成器运行的动画和由 Timer/RAF 驱动的 JS 动画两类,因为前者可以认为是后者的一个简化版本,所以这一章主要讨论 Timer/RAF 驱动的 JS 动画. 5.1 动画流水线 从上图可以看出非合成器动画的流水线比合成器动画更长更复杂,并且非合成器动画的后半段跟合成器动画是一致的. JavaScipt 部分是页端实现的逻辑,可能包含了计算的部分,和调用浏览器提供的 API 的部分(修改 DO

Chrome 渲染流水线演化的未来

前段时间我写了一篇文章浏览器渲染流水线解析与网页动画性能优化,对目前 60 左右版本的 Chrome 的渲染流水线进行解析,文末也讨论了当前渲染流水线的一些不足和未来演化的方向. 当前的渲染流水线过于复杂和冗长,特别是对于非合成器动画来说,过多的线程/进程间交互增加了不少额外开销,异步光栅化的机制也是有利于合成器动画而不利于非合成器动画.而未来的演化理应需要简化渲染流水线,减少线程/进程间交互,避免非必要的额外开销,光栅化和合成不再像现在一样泾渭分明,渲染流水线可以支持更灵活和动态自适应的图层化

【Web动画】CSS3 3D 行星运转 && 浏览器渲染原理

承接上一篇:[CSS3进阶]酷炫的3D旋转透视 . 最近入坑 Web 动画,所以把自己的学习过程记录一下分享给大家. CSS3 3D 行星运转 demo 页面请戳:Demo.(建议使用Chrome打开) 本文完整的代码,以及更多的 CSS3 效果,在我 Github 上可以看到,也希望大家可以点个 star. 嗯,可能有些人打不开 demo 或者页面乱了,贴几张效果图:(图片有点大,耐心等待一会) CSS3 3D 行星运转效果图 随机再截屏了一张: 强烈建议你点进 Demo页感受一下 CSS3

浏览器渲染过程与性能优化

大家都知道万维网的应用层使用了 HTTP 协议,并且用浏览器作为入口访问网络上的资源.用户在使用浏览器访问一个网站时需要先通过 HTTP 协议向服务器发送请求,之后服务器返回 HTML 文件与响应信息.这时,浏览器会根据 HTML 文件来进行解析与渲染(该阶段还包括向服务器请求非内联的 CSS 文件与 JavaScript 文件或者其他资源),最终再将页面呈现在用户面前. 现在知道了网页的渲染都是由浏览器完成的,那么如果一个网站的页面加载速度太慢会导致用户体验不够友好,本文通过详解浏览器渲染页面

草料Chrome浏览器插件,让二维码更好用

安装插件草料chrome插件,是专为chrome核心的浏览器开发的一个二维码应用增强工具插件. 自动将地址栏链接生成二维码 以谷歌原生的chrome浏览器为例,插件安装成功后会在浏览器地址栏旁边出现一个绿色的插件按钮.每次打开一个链接,按下这个按钮就可以将地址栏的链接生成二维码. 生成图案简单的短网址二维码 如果链接过长,生成的二维码图案会太复杂,不易于扫描,还可以选择点击弹出窗上的短网址选项,转成短网址二维码,图案变的简单多了. 将页面上任意一段文字生成二维码 有时候看到页面上一段精彩的文字,

使用zxing工具包创建和解析二维码

关于二维码是什么,以及二维码是如何生成的,我也没有研究得很深入,就不多说了,以免误导大家.请参看: java 二维码原理以及用java实现的二维码的生成.解码 二维码的生成细节和原理 下面是一个可以生成和解析二维码的工具类,该类用到了zxing工具包,我通过Maven去下载的: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 <dependencies>     <!-- JavaSE包依赖于Core包,因此Core包不需要直接依赖了     <dependency

css的效率和浏览器渲染的速度

浏览器如何读取你的CSS选择器有一个很重要的原则,那就是它们从右到左读取.这意味这像 ul > li a[title="home"] 这样的选择器,a[title="home"] 将是最先被读取的. 我承认我并不经常想这个问题......我们写的css的效率是怎么样的呢,浏览器渲染的速度又如何呢? 这是应该是浏览器开发者应该关心的(页面加载更快,用户就会更愉快).Mozilla有一篇文章: about best practices . Google 当然也很关