持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第30天,点击查看活动详情
核心描述
个人理解渲染合成层,其实是通过一些隐形或显形的设置,触发浏览器的渲染前的优化机制,从而提高整个页面的渲染性能。
-
什么是渲染合成层:
- 合成就是将页面的各个部分分成多个层、单独光栅化(浏览器根据文档的结构、每个元素的样式、页面的几何形状和绘制顺序转换为屏幕上的像素的过程)它们并在合成器线程中合成为一个页面的技术。
- 满足某些特殊条件的渲染层,会被浏览器自动提升为合成层。合成层拥有单独的 GraphicsLayer,而其他不是合成层的渲染层,则和其第一个拥有 GraphicsLayer 的父层共用一个。
-
怎么触发合成层:
- 显示触发
- 具有 CSS3D 属性 CSS 透视效果
- 包含的 RenderObject 节点表示的是使用硬件加速的视频解码技术的 HTML5video 元素
- 包含的 RenderObject 节点包含使用了硬件加速的 Canvas2D 或 WebGL 技术
- 使用 CSS 透明效果或 CSS 变形动画(使用 will-change 属性)
- 使用了硬件加速的 CSS Filters 技术(有的文献中表示 filters 属性并没有提升为合成层的效果,推测只有一部分 filters 滤镜效果需要使用硬件加速,并非所有)
- 使用了剪裁 Clip 或者反射 Reflection,并且它的后代中包含一个合成层
- 拥有一个Z坐标比自己小的兄弟节点,且该节点是一个合成层。
- 隐式触发
- 一个或多个非合成元素应出现在堆叠顺序上的合成元素之上,会被提升为合成层。
- 显示触发
-
合成层的优缺点
- 优点:
- 合成层的位图,会交由 GPU 合成,比 CPU 处理要快得多;
- 当需要 repaint 时,只需要 repaint 本身,不会影响到其他的层;
- 元素提升为合成层后,transform 和 opacity 才不会触发 repaint,如果不是合成层,则其依然会触发 repaint。
- 缺点:
- 绘制的图层必须传输到 GPU,这些层的数量和大小达到一定量级后,可能会导致传输非常慢,进而导致一些低端和中端设备上出现闪烁;
- 隐式合成容易产生过量的合成层,每个合成层都占用额外的内存,而内存是移动设备上的宝贵资源,过多使用内存可能会导致浏览器崩溃,让性能优化适得其反。
- 优点:
-
什么是层压缩
- 层隐式合成的例子,可能简单的重叠就会产生大量的合成层,这样会占用很多无辜的 CPU 和 内存资源,严重影响了页面的性能。这一点浏览器也考虑到了,因此就有了层压缩(Layer Squashing)的处理。
- 浏览器的自动层压缩并不是万能的,有很多特定情况下,浏览器是无法进行层压缩的。比如 video 元素的渲染等。
-
什么是层爆炸
- 同合成层重叠也会使元素提升为合成层,虽然有浏览器的层压缩机制,但是也有很多无法进行压缩的情况。也就是说除了我们显式的声明的合成层,还可能由于重叠原因不经意间产生一些不在预期的合成层,极端一点可能会产生大量的额外合成层,出现层爆炸的现象。
- 解决层爆炸的问题,最佳方案是打破 overlap 的条件,也就是说让其他元素不要和合成层元素重叠,譬如巧妙的使用 z-index 属性。
-
如何查看渲染合成层(以 Chrome 为例:
知识拓展
- 浏览器渲染流程:
JavaScript 执行
->Style 计算
->Layout 布局
->Paint 绘制
->Composite 合成
- JavaScript :一般来说,我们会使用 JavaScript 来实现一些视觉变化的效果。比如做一个动画或者往页面里添加一些 DOM 元素等。
- Style 样式计算:根据 CSS 选择器,对每个 DOM 元素匹配对应的 CSS 样式。这一步结束之后,就确定了每个 DOM 元素上该应用什么样的 CSS 样式规则。
- Layout 布局:确定了每个 DOM 元素的样式规则之后,这一步具体计算每个 DOM 元素最终在屏幕上显示的大小和位置。WEB 页面中元素的布局是相对的,因此一个元素的布局发生变化,会联动的引发其他元素的布局发生变化。比如 body 元素的宽度变化会影响到其子元素的宽度,其子元素的宽度变化也会继续对其孙子元素产生影响。因此对于浏览器来说,Layout 布局阶段是经常发生的。
- Paint 绘制:本质上就是填充像素的过程。包括绘制文字、颜色、图像、边框和阴影等,也就是一个 DOM 元素所有的可视效果。一般来说,这个绘制过程是在多个层上完成的。
- Composite 渲染层合成:页面中 DOM 元素的绘制是在多个层上进行的。在每个层上完成绘制过程之后,浏览器会将所有层按照合理的顺序合并成一个图层,然后显示在屏幕上。对于有位置重叠的元素页面,这个过程尤其重要,因为一旦图层的合并顺序出错,将会导致元素显示异常。
- 图形层(GraphicsLayer)
- GraphicsLayer 其实是一个负责生成最终准备呈现的内容图形的层模型,它拥有一个图形上下文(GraphicsContext),GraphicsContext 会负责输出该层的位图。存储在共享内存中的位图将作为纹理上传到 GPU,最后由 GPU 将多个位图进行合成,然后绘制到屏幕上,此时,我们的页面也就展现到了屏幕上。
- GraphicsLayer 是一个重要的渲染载体和工具,但它并不直接处理渲染层,而是处理合成层。
- 个人理解:很多优化技术,只有在遇到了,再去实践才是最佳实践。因为没有深入的理解和实践,盲目的引入,反而会引发一些不可预知的问题。尤其是当业务还没有达到需要优化的阶段,还是应该以业务为主。
参考资料
- 无线性能优化:Composite:fed.taobao.org/blog/taofed…
- MDN-will-change:developer.mozilla.org/zh-CN/docs/…
- 浏览器渲染魔法之合成层:segmentfault.com/a/119000004…
- 高性能Web动画和渲染原理系列(5)合成层的生成条件和陷阱:www.cnblogs.com/dashnowords…
- 详谈层合成(composite):juejin.cn/post/684490…
- 硬件加速不是银弹:chenng.cn/posts/%E7%A…
- 重排和重绘是什么,有什么区别:juejin.cn/post/710184…
- 浏览器合成与渲染层优化:cloud.tencent.com/developer/a…
浏览知识共享许可协议
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。