关于硬件渲染了解一下

4,189 阅读4分钟

浏览器的渲染方式,主要分为两种,第一种是软件渲染,第二种是硬件渲染。如果绘制工作只是由 CPU 完成,那么称之为软件渲染,如果绘制工作由 GPU 完成,则称之为硬件渲染。软件渲染与硬件渲染有不同的缓存机制,只要我们合理利用,就能发挥出最好的效果。

开启

浏览器还有一种名为硬件渲染的渲染方式,它是使用 GPU 的硬件能力来帮助渲染页面,那么是怎么设置的?

  • 启用硬件加速 在chrome的地址栏中输入chrome://settings/回车滚动页面到地步,点击显示高级设置再次滚动到页面地步,找到使用硬件加速模式
  • 开启gup硬件加速 在chrome的地址栏中输入chrome://flags/#disable-accelerated-video-decode找到硬件加速的视频解码,点击启用

完成上面两步后重启浏览器

能做什么

大家都知道在页面性能优化的时候都会用到 GPU 加速硬件加速类似方式,浏览器一帧(1000/16ms)会依次执行以下,减少或者避免 layout,paint 可以让页更加流畅:

  1. JavaScript:JavaScript 实现动画效果,DOM 元素操作等。
  2. Style(计算样式):确定每个 DOM 元素应该应用什么 CSS 规则。
  3. Layout(布局):计算每个 DOM 元素在最终屏幕上显示的大小和位置。由于 web 页面的元素布局是相对的,所以其中任意一个元素的位置发生变化,都会联动的引起其他元素发生变化,这个过程叫 reflow。
  4. Paint(绘制):在多个层上绘制 DOM 元素的的文字、颜色、图像、边框和阴影等。
  5. Composite(渲染层合并):按照合理的顺序合并图层然后显示到屏幕上。

一个页面是由多个图层最后形成一个完整的合成层才被渲染出来效果就像这样:

渲染图

硬件渲染 WebKit 会依据指定条件决定将那些 RenderLayer 对象组合在一起形成一个新层并缓存在 GPU,这些新层我们统称为合成层(Compositing Layer)。这些合成层提升成独立的层,被独立出来之后,便不会再影响其他 dom 的布局。如果发生 偏移、透明度等等变换 GPU 要做的只是把更新的合成层进行相应的变换并送入 Compositor 重新合成即可,利用这个优点我们可以把页面中一些布局经常变换的 dom 提升到独立的层。

在上图中黄色边框表示放到了一个新的复合层(composited layer)中渲染,左侧的列表里列出页面里存在哪些渲染层,右侧的 Details 显示的是这些渲染层的详细信息,包括渲染层的大小、形成原因等。

如何触发合成层

  1. 根节点 document
  2. HTML5 Video或者Canvas元素。
  3. 元素有一个 z-index 较低且包含一个复合层的兄弟元素
  4. 3D 或透视变换(perspective,transform) CSS 属性 比如常用的 (设置translateZ()、backface-visibility为hidden)

注意事项

也就是上面第三条,英文原版是这么说

Element has a sibling with a lower z-index which has a compositing layer (in other words the it’s rendered on top of a composited layer)

意思是,如果有一个元素,它的兄弟元素在复合层中渲染,而这个兄弟元素的 z-index 比较小,且两个元素有重叠(显式的重叠比如可以通过 margin 的负值来实现,隐式的重叠比如未指定自己及浮动层兄弟元素的 z-index),那么这个元素(不管是不是应用了硬件加速样式)也会被放到复合层中。

所以用轮播、动画loading等页面的时候要注意下要遵循最小化影响原则,如果调试看到有很多 黄色边框 就要注意了。

使用 3D 硬件加速提升动画性能时,最好给元素增加一个 z-index 属性,人为干扰复合层的排序,可以有效减少 chrome 创建不必要的复合层,提升渲染性能,移动端优化效果尤为明显。

关于 CSS3 will-change

前面说的那些有点hach,CSS3 will-change 才是正规军是属于 web 标准属性,兼容性这块 Chrome/FireFox/Opera 是支持的,他是提前通知浏览器元素将要做什么动画,让浏览器提前准备合适的优化设置,具体值:

/* 关键字值 */
will-change: auto;
will-change: scroll-position;
will-change: contents;
will-change: transform;        /* <custom-ident>示例 */
will-change: opacity;          /* <custom-ident>示例 */
will-change: left, top;        /* 两个<animateable-feature>示例 */

/* 全局值 */
will-change: inherit;
will-change: initial;
will-change: unset;

will-change 虽然可以加速,但是不可滥用。。。