不了解回流重绘的,推荐看一下这篇文章:相信身为前端的你,对回流(重新布局)和重绘多少有点了解,网上也有一堆文章资料讲它两的关系及优化。 所以这篇文章就不重复这些知识了,这里我主要想简单地谈一谈它们性能消耗的问题,如:为什么回流会更耗性能?底层原因到底是什么?为什么脱离文档流、gpu加速可以减少性能消耗?
为什么回流会更耗性能?
先讲讲回流和重绘的执行顺序
想必大家都很清楚:回流>重绘
这也可以解释为什么回流必定触发重绘?原因:需要先通过回流对dom元素进行定位&大小计算,才能知道要绘制到哪个位置,绘制的范围是多少。
为什么触发重绘未必触发回流?因为位置大小变了,原来绘制的样式已经不适用了,需要重新绘制
所以触发回流的计算量>重绘的计算量,因而回流的性能消耗更大。 当然,这只是表层原因。位置大小没变,没必要重新计算,只需要重新绘制相关样式即可
了解CPU和GPU渲染之间的差异
要更深层了解回流耗性能这个问题,先需要了解cpu和gpu渲染性能之间的差异,下面这个视频可以很好表明两者的工作原理。
# NVIDIA现场形象展示CPU和GPU工作原理上的区别
简单来说:
CPU:
- 核心数少
- 单核性能强
- 适合做逻辑复杂的计算
- 串行执行
GPU:
- 核心数多(是cpu的成百上千倍)
- 单核性能不如cpu
- 只能做一些简单的逻辑计算(如:矩阵运算)
- 可以并行执行
那这个和我们说的回流有什么关系呢?别急,往下看
回流&重绘、CPU、GPU之间的关系
要知道,计算机的图像显示跟GPU脱不了关系,没有GPU,你就看不见丰富多彩的图片的,而GPU的渲染流程大致可以简化成下面这几个步骤:
更具体的可以看一下这篇文章:# 计算机原理|计算机图形渲染原理
看不懂也没关系,这里只是想说明,GPU渲染图片需要CPU传递数据,拿到数据才能做渲染工作。
让我们回到正题,回流&重绘的数据计算(位置、大小、颜色信息等)是完全由浏览器的渲染引擎在 CPU 上计算,基于文档流模型、CSS 规则等,决定每个元素的几何布局,然后将这些几何信息传递给 GPU 用于绘制的。
- CPU将数据打包:顶点数据(如位置)、纹理数据(如图片)、着色器参数等,并通过图形API(如OpenGL、DirectX或Metal)传递给GPU。
- 一旦GPU接收到数据,它会执行着色器程序(如顶点着色器和片元着色器),这些程序负责处理和渲染图形数据。
- GPU擅长并行处理,它可以同时处理大量的像素或顶点,这使得复杂的绘制任务能够高效完成。
- 在GPU完成各个图层的渲染后,会将这些图层合成到一起,形成最终的画面。
然而CPU与GPU之间传递数据是比较耗性能一个环节(调用GPU绘图环节)?
上述可知,GPU绘图速度是很快的,而CPU和GPU传递数据需要时间,如果GPU渲染完一张图后,CPU还没处理完下一张活的数据,或者来不及传递数据,那GPU就只能干等着。一般CPU都会一次性将大部分数据传给GPU做缓存,减少传递次数。
所以这也就是为什么频繁触发回流会导致性能消耗问题,不仅仅是因为CPU要重复计算相关数据,而且还会增加CPU向GPU传递数据的次数。
为什么不换成GPU去做计算呢?
可能有小伙伴会问:那既然这样,将计算&渲染工作都交给GPU不就得了,为啥还要用CPU去计算?
- 首先,上面已经说过了,CPU单核性能很强,适合做复杂的逻辑计算,像是网页这种复杂的布局更适合用CPU。
- 其次,页面元素需要从上往下一一计算,因为他们之间的位置大小信息是互相影响的(脱离文档流的除外),更适合串行执行计算。
- 而且,让开发者直接面向GPU编程(也就是写shader),那难度可比现在写html+css高不知道多少级别,不利于开发和维护。
- 从应用场景来看,网页不像游戏,对实时渲染没太大需求,也就没必要让开发者直接面对底层GPU的api了。
浏览器的渲染引擎已经帮助开发者做了很多内置功能,基于html+css已经足够应对各种页面需求了。
如果还想折腾更底层或者更酷炫的效果,可以去学一下webgl、图形学、shader。
硬件(GPU)加速原理
通过上面所说,其实可以比较好理解GPU加速是怎么回事了。
通过利用css中的transform、opacity、filter等属性,做GPU加速,将大部分计算工作量交给了GPU,减少了CPU与GPU直接的数据传递次数,从而提高性能。
这里要说一下,脱离文档流的不一样全是做了GPU加速,但做了GPU加速的一定是脱离了文档流的,
因为GPU加速,会把元素单独放到一个图层上做渲染,渲染完后才会合并图层,也就是脱离了原来的文档流。
总结
- 频繁触发回流重绘,不仅增加CPU计算量,还好增加CPU与GPU的数据交换次数,从而导致性能瓶颈。
- 利用GPU加速,将部分计算工作交给GPU可以减少CPU的性能消耗,减少数据交换次数