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

简介:

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 节点和图层作为占位符来避免加载后的图层结构发生剧烈变化。

目录
相关文章
|
3月前
|
Web App开发 前端开发
Chrome 浏览器插件 V3 版本 Manifest.json 文件中 Action 的类型(Types)、方法(Methods)和事件(Events)的属性和参数解析
Chrome 浏览器插件 V3 版本 Manifest.json 文件中 Action 的类型(Types)、方法(Methods)和事件(Events)的属性和参数解析
154 0
|
2月前
|
XML 机器学习/深度学习 JSON
在火狐浏览器调ajax获取json数据时,控制台提示“XML 解析错误:格式不佳”。
在火狐浏览器调ajax获取json数据时,控制台提示“XML 解析错误:格式不佳”。
29 0
在火狐浏览器调ajax获取json数据时,控制台提示“XML 解析错误:格式不佳”。
|
6天前
|
缓存 图形学 异构计算
【Shader渲染流水线流程】
【Shader渲染流水线流程】
|
29天前
|
存储 编解码 算法
【解码与渲染 异常情况】深入解析视频中绿色竖线现象(二)
【解码与渲染 异常情况】深入解析视频中绿色竖线现象
38 1
|
2月前
|
消息中间件 JavaScript 前端开发
前端秘法进阶篇----这还是我们熟悉的浏览器吗?(浏览器的渲染原理)
前端秘法进阶篇----这还是我们熟悉的浏览器吗?(浏览器的渲染原理)
|
2月前
|
存储 缓存 JavaScript
|
3月前
|
前端开发 JavaScript 数据可视化
探索浏览器的内心世界:渲染机制的奥秘
探索浏览器的内心世界:渲染机制的奥秘
探索浏览器的内心世界:渲染机制的奥秘
|
3月前
|
消息中间件 前端开发 Java
【面试题】前端必修-浏览器的渲染原理
【面试题】前端必修-浏览器的渲染原理
|
3月前
|
Web App开发 存储 前端开发
Chrome 浏览器的隐身窗口(incognito window)功能解析
Chrome 浏览器的隐身窗口(incognito window)功能解析
92 0
|
5月前
|
JSON 前端开发 数据格式
ajax请求解析json数据渲染在前端界面
ajax请求解析json数据渲染在前端界面
26 0

热门文章

最新文章

推荐镜像

更多