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

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介:

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 线程所阻塞。

目录
相关文章
|
16天前
|
JavaScript 前端开发 Go
CSS 与 JS 对 DOM 解析和渲染的影响
【10月更文挑战第16天】CSS 和 JS 会在一定程度上影响 DOM 解析和渲染,了解它们之间的相互作用以及采取适当的优化措施是非常重要的。通过合理的布局和加载策略,可以提高网页的性能和用户体验,确保页面能够快速、流畅地呈现给用户。在实际开发中,要根据具体情况进行权衡和调整,以达到最佳的效果。
|
7天前
|
域名解析 缓存 网络协议
浏览器中输入URL返回页面过程(超级详细)、DNS域名解析服务,TCP三次握手、四次挥手
浏览器中输入URL返回页面过程(超级详细)、DNS域名解析服务,TCP三次握手、四次挥手
|
10天前
|
缓存 前端开发 JavaScript
"面试通关秘籍:深度解析浏览器面试必考问题,从重绘回流到事件委托,让你一举拿下前端 Offer!"
【10月更文挑战第23天】在前端开发面试中,浏览器相关知识是必考内容。本文总结了四个常见问题:浏览器渲染机制、重绘与回流、性能优化及事件委托。通过具体示例和对比分析,帮助求职者更好地理解和准备面试。掌握这些知识点,有助于提升面试表现和实际工作能力。
42 1
|
22天前
|
Web App开发 SQL 数据库
使用 Python 解析火狐浏览器的 SQLite3 数据库
本文介绍如何使用 Python 解析火狐浏览器的 SQLite3 数据库,包括书签、历史记录和下载记录等。通过安装 Python 和 SQLite3,定位火狐数据库文件路径,编写 Python 脚本连接数据库并执行 SQL 查询,最终输出最近访问的网站历史记录。
|
21天前
|
JavaScript API
深入解析JS中的visibilitychange事件:监听浏览器标签间切换的利器
深入解析JS中的visibilitychange事件:监听浏览器标签间切换的利器
55 0
|
26天前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
60 0
|
26天前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
49 0
|
26天前
|
存储 Java C++
Collection-PriorityQueue源码解析
Collection-PriorityQueue源码解析
58 0
|
26天前
|
安全 Java 程序员
Collection-Stack&Queue源码解析
Collection-Stack&Queue源码解析
72 0
|
7天前
|
消息中间件 缓存 安全
Future与FutureTask源码解析,接口阻塞问题及解决方案
【11月更文挑战第5天】在Java开发中,多线程编程是提高系统并发性能和资源利用率的重要手段。然而,多线程编程也带来了诸如线程安全、死锁、接口阻塞等一系列复杂问题。本文将深度剖析多线程优化技巧、Future与FutureTask的源码、接口阻塞问题及解决方案,并通过具体业务场景和Java代码示例进行实战演示。
26 3

推荐镜像

更多