每天一小步 <何为硬件加速>

958 阅读5分钟

前言

在正片开始前,请允许我先抛一块砖👇

使用translate改变位置和使用position改变位置有什么区别?

直接说答案吧:

translatetransform的一个值

改变transform并不会触发回流和重绘,只会触发复合。但改变position会直接导致回流和重绘。而且transformGPU创建图层,positionCPU创建图层,因此从的性能上而言,使用translate来移动对象是一个更好的选择

上面的回答又引伸出了两个问题:

  1. transform只触发复合,而不触发回流重绘
  2. 硬件加速能提高性能?

transform只触发复合,而不触发回流重绘

这里出现了一个相对偏门一点的词 -- 复合。那这个复合到底是什么东西,还得先从浏览器的渲染流程说起(以下内容参考:层叠上下文 渲染图层 复合图层(硬件加速)区别与联系,并且讲述主体为chrome浏览器)

渲染图层(Render Layer)与复合图层(Graphics Layer)关系

先来看一下这张图片👇

chrome图层.png

这是chrome的简单渲染流程关系,可以看到在Layer trees部分中,Render LayerGraphics Layer是两个独立的流程。简单的理解就是,拥有层叠上下文属性的元素会生成一个新的层叠上下文对象,每个层叠上下文对象都是一个渲染图层,渲染图层与复合图层是不同的概念,渲染图层更像是一个纯二维的概念,无论其怎么层叠覆盖最终都归依于根层叠上下文。而复合图层完全脱离根层叠上下文,相当于开辟新的位面

那么来简单概括一下这两个图层:

  • 渲染图层是页面普通的文档流,虽然可以通过浮动、绝对定位等方法脱离文档流,但仍属于根层叠上下文,共用一个绘图上下文对象
  • 复合图层每一层都会由系统独立分配资源,并形成一个独立的绘图上下文对象,而且脱离文档流,因此不会引起渲染图层中的回流或重绘

transform真的只触发复合

了解了复合之后,让我们来实践一下,看看transform是否真的只触发复合,而没有回流和重绘

浅创建一个一直执行transform动画的盒子,然后观察控制台的绘制指令有没有增加

<style>
@keyframes move {
    0% {
        transform: translateX(0);
    }
    100% {
        transform: translateX(1000px);
    }
}

#composited {
    width: 200px;
    height: 200px;
    background: red;
    position: absolute;
    left: 0;
    top: 0;
    animation: move 10s infinite;
}
</style>

<div id="composited" class="both">composited</div>

看一下控制台的绘制指令有没有变化👇

transform不引起重绘1.gif

可以发现,即使让系统重新计算绘制指令也没有新的增加,由此可以得出结论,transform确实没有引起回流和重绘

硬件加速能提高性能?

在上文中提到过,translate是由GPU控制的一个独立的图层,因此不会引起回流和重绘,那么是否translate的性能就优于position呢?别着急,让我们先从GPUCPU的区别开始讲起

CPUGPU的区别

CPU是计算机的大脑,我们写的程序最终会通过CPU指令来控制计算机执行,它会对指令进行编码,然后通过逻辑电路来执行该指令,执行的流程分成了多个阶段,执行完一个流程就是一个指令周期,而CPU就是不断地执行指令周期来完成各种任务。

GPU是显卡的大脑,主要负责加速图形处理速度,决定了显卡的档次和大部分功能,同时也是2D显卡3D显卡的区别所在。2D显卡芯片在处理3D图像和特效时需要CPU的协助,而3D显卡芯片则集中在显示芯片中,也就是所谓的硬件加速功能。

二者的主要区别就在于芯片内的缓存体系数字逻辑运算单元的结构差异:

  • CPU的核数不多,但胜在每个核都有足够大的缓存和数字逻辑运算单元,因此可以胜任很多复杂逻辑判断
  • GPU的核数远超CPU,但每个核的缓存较小而且数字逻辑运算单元较为简单,因此常运用于计算多个节点运动的动画中

如何使用硬件加速

  • 最常用的方式:transformopcacity
  • will-change属性
  • <vedio><iframe><canvas>等元素

硬件加速的注意事项

在使用硬件加速时,尽可能加上z-index来防止浏览器给后续的元素重复创造复合层

它的原理是:

webkit CSS3中,如果一个元素添加了硬件加速,并且z-index的层级较低,那么层级高于或等于该元素,并且relative或absolute属性相同的元素会默认变为复合层渲染,处理不当则会极大地影响性能

硬件加速 OR NOT?

通过上面的比较可以发现,对于处理动画而言,似乎GPU是个更好的选择,因为它帮助CPU完成了部分的图形绘制工作,减轻了CPU的负担

那么下面就通过实践看看GPU是否真的减轻了CPU的负担👇

还是刚才的例子,但是把盒子的数量增加到5个,分别通过transformpositon方式移动盒子,并在任务管理器中查看CPU的使用率

transform👇维持在3%到6%之间

后台transform.gif

position👇最高甚至达到11%

后台position.gif

可以很明显地看到,使用transformpostionCPU占用率区别还是挺大的,由此也得出结论:使用GPU确实可以减轻CPU的负担

那么这是不是就意味着可以随意在项目中使用硬件加速来优化性能呢?NO NO NO~

  • 内存。如果GPU加载了大量的纹理,那么就很容易发生内存过载的问题,尤其是移动端浏览器
  • GPU渲染会影响文字的抗锯齿效果,在动画过程中文字可能会变得模糊不清

硬件加速虽好,可不要贪杯哦

结语

要是有任何写错或者需要求改的地方,恳请指出,感激不尽~