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

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

4 合成器动画性能分析和优化指南

4.1 动画流水线

Compositor Animation

上图显示了合成器动画的渲染流水线示意图,根据 Android WebView 平台的实现进行绘制,其它平台可能略微不同,但对后面的性能分析,在大部分情况下影响不大

整个流水线的大概过程是:

  1. 位于 Browser 进程 UI 线程的窗口管理器接收到来自操作系统的屏幕刷新垂直同步信号(VSync),开始准备输出新的一帧,它首先给位于 Renderer 进程 Compositor 线程的 Layer Compositor 发送一个 Begin Frame 消息;
  2. Layer Compositor 接收到 Begin Frame 消息后,更新合成器内部的状态机,开始准备输出 Compositor Frame,在这个过程中的一个重要动作就是 Animate,合成器会检查当前是否有正在运行的动画,然后运行这些动画,并根据动画运行的结果改变关联图层的对应属性(比如惯性滚动动画改变图层的 Scroll Offset,Transform 动画改变图层的 Transform),Animate 的结果会发送回给 UI 线程告诉其是否有动画正在运行,需要更新窗口;
  3. 如果 UI 线程确定合成器需要更新窗口,则会发送一个 Draw 消息请求合成器输出下一帧 Compositor Frame;
  4. 合成器按下面的过程产生新的 Compositor Frame 并发送给 Display Compositor; 4.1 合成器找出在当前可见区域内显示的图层; 4.2 合成器找出这些图层在可见区域内的分块; 4.3 如果该分块已经有分配 Resource(说明此分块已经完成光栅化),则产生一个 Draw Quad 的命令置入 Compositor Frame 中,如果没有则跳过;
  5. Display Compositor 接受到新的 Compositor Frame 后,对 Compositor Frame 进行 Render,将每一个 Draw Quad 命令转换成一个 GL Draw Call,然后 GPU 执行所有的 GL 指令完成最后的窗口绘制;

上述流程的一些关键点是:

  1. Draw 的过程中,合成器不会等待可见的分块光栅化完成,这让合成器充分利用了异步光栅化的机制来提升性能,但是也会造成动画过程中可能会出现空白的分块,比如快速滚动页面有时会看到空白区域;
  2. 在合成器动画过程中,Layer Compositor 和 Display Compositor 是异步并发的,在 Display Compositor 输出 GL Frame N 的时候,Layer Compositor 已经可以开始输出下一帧 Compositor Frame N + 1;

4.2 动画耗时分析

  1. Begin Frame 的耗时一般很短,大概 1 ~ 2 毫秒左右;
  2. Draw 的耗时也不长,一般不超过 5 毫秒,耗时主要取决于网页的图层复杂度,总的来说合成器动画过程中 Compositor 线程的开销一般都不会构成性能瓶颈;
  3. Render 的耗时也不长,一般也是不超过 5 毫秒,耗时主要取决于当前可见区域内的可见分块的数量;
  4. GPU 部分的耗时比较长,耗时主要取决于当前可见区域内的可见分块的总面积,也就是绘制的总面积,一旦 Render + GPU 部分的耗时大于 16.7 毫秒,动画就会出现掉帧;

总的来说影响合成器动画性能的最关键因素就是过度绘制系数(Overdraw,可以理解为绘制的面积和可见区域面积的比例),如果网页本身存在大量图层堆叠情况,导致过度绘制系数过高,就会严重影响合成器动画的性能。经验显示,过度绘制系数比较理想的值是在 2 以内,一般建议不超过 3,这样可以保证在中低端的移动设备上也有不错的性能表现。

另外,合成器动画过程中,Compositor 和 GPU 线程是前台线程,它们虽然理论上不会被 Worker 和 Renderer 线程阻塞,但是在真实的运行场景中,移动设备的 CPU/GPU 和内存带宽等硬件资源是有限的,如果 Worker 和 Renderer 线程处于高负荷状态下,也会导致前台的 Compositor 和 GPU 线程阻塞,最终导致合成器动画掉帧。

这种现象常见于:

  1. 网页在合成器动画比如惯性滚动过程中,有大量的 JS 加载图片或者其它内容,并频繁地对 DOM 树进行操作;
  2. 网页的图层树非常复杂,并且其结构在合成器动画过程中频繁发生变化,导致大量的光栅化任务在 Worker 线程运行;

4.3 动画性能优化 Checklist

根据上述的耗时分析,我们可以给出一个页端优化合成器动画性能的简单 Checklist

  1. 检查网页的图层结构是否合理,包括深度和数量,一般来说深度在 10 以内,数量在 100 以内是比较合理的值;
  2. 检查网页的合成器动画,包括网页的惯性滚动,各种图层的淡入/淡出等动画,在动画过程中,是否同时存在大量的网络加载和 DOM 操作,网页图层结构是否保持稳定;
  3. 当网页处于任一滚动位置上时,它的当前过度绘制系数是否合理;

如何判断网页的图层结构是否稳定,一般而言,如果是位于叶子节点的图层增加或者移除,对整个图层结构影响并不大,但是如果是中间节点的图层增加或者移除,对图层结构的影响就比较大了,并且越是接近根节点,影响就越大。

现在的页端都会大量使用异步加载来优化加载性能和流量,但是容易出现导致动画掉帧的现象。要平衡好这一点意味着需要实现一个加载和关联 DOM 操作的调度器,如果检查到动画正在运行,则停止加载或者通过节流阀机制降低加载的并发数量和频率,同时可以通过事先生成相应的 DOM 节点和图层作为占位符来避免加载后的图层结构发生剧烈变化。

目录
相关文章
|
2月前
|
存储 前端开发 开发者
|
1月前
|
域名解析 缓存 网络协议
浏览器中输入URL返回页面过程(超级详细)、DNS域名解析服务,TCP三次握手、四次挥手
浏览器中输入URL返回页面过程(超级详细)、DNS域名解析服务,TCP三次握手、四次挥手
|
15天前
|
前端开发 JavaScript
宏任务和微任务在浏览器渲染过程中的执行顺序
宏任务和微任务是浏览器事件循环中的两种任务类型。宏任务包括整体代码块、setTimeout等,微任务有Promise.then、MutationObserver等。每个宏任务执行完毕后,会先执行完所有微任务,再进行下一轮渲染或执行下一个宏任务。
|
15天前
|
JavaScript 前端开发 API
浏览器渲染过程中如何处理异步任务
在浏览器渲染过程中,异步任务通过事件循环机制处理。JS执行时,同步任务在主线程上执行,形成一个执行栈。异步任务则被推入任务队列中,待主线程空闲时按顺序调用,确保页面流畅渲染与响应。
|
1月前
|
缓存 前端开发 JavaScript
"面试通关秘籍:深度解析浏览器面试必考问题,从重绘回流到事件委托,让你一举拿下前端 Offer!"
【10月更文挑战第23天】在前端开发面试中,浏览器相关知识是必考内容。本文总结了四个常见问题:浏览器渲染机制、重绘与回流、性能优化及事件委托。通过具体示例和对比分析,帮助求职者更好地理解和准备面试。掌握这些知识点,有助于提升面试表现和实际工作能力。
65 1
|
2月前
|
缓存 自然语言处理 前端开发
浏览器渲染
【10月更文挑战第28天】浏览器渲染涉及将HTML、CSS和JavaScript代码转换为可视网页,主要步骤包括:解析HTML构建DOM树、解析CSS构建CSSOM树、合并DOM与CSSOM生成渲染树、布局确定元素位置和尺寸、绘制元素到屏幕、合成图层形成最终图像。此过程不断优化以提升性能。
|
2月前
|
Web App开发 SQL 数据库
使用 Python 解析火狐浏览器的 SQLite3 数据库
本文介绍如何使用 Python 解析火狐浏览器的 SQLite3 数据库,包括书签、历史记录和下载记录等。通过安装 Python 和 SQLite3,定位火狐数据库文件路径,编写 Python 脚本连接数据库并执行 SQL 查询,最终输出最近访问的网站历史记录。
36 4
|
2月前
|
JavaScript API
深入解析JS中的visibilitychange事件:监听浏览器标签间切换的利器
深入解析JS中的visibilitychange事件:监听浏览器标签间切换的利器
139 0
|
4月前
|
弹性计算 运维 Serverless
项目管理和持续集成系统搭建问题之云效流水线支持阿里云产品的企业用户如何解决
项目管理和持续集成系统搭建问题之云效流水线支持阿里云产品的企业用户如何解决
83 1
项目管理和持续集成系统搭建问题之云效流水线支持阿里云产品的企业用户如何解决
|
4月前
|
敏捷开发 Java 测试技术
阿里云云效产品使用合集之如何下载流水线构建过程中生成的jar
云效作为一款全面覆盖研发全生命周期管理的云端效能平台,致力于帮助企业实现高效协同、敏捷研发和持续交付。本合集收集整理了用户在使用云效过程中遇到的常见问题,问题涉及项目创建与管理、需求规划与迭代、代码托管与版本控制、自动化测试、持续集成与发布等方面。

推荐镜像

更多