CSS动画的性能分析和浏览器GPU加速

此文已由做者袁申受权网易云社区发布。
html

欢迎访问网易云社区,了解更多网易技术产品运营经验。html5

有数的数据大屏能够在一块屏幕上展现若干张不一样的图表,以炫酷的方式展现各类业务数据。其中有些图表使用CSS实现了饼图轮播、地图标记点闪烁等动画,然而在一张大屏上同时显示了许多张图表时,持续的动画效果有时会出现掉帧、卡顿的状况,须要对动画性能进行优化。本文简单介绍了chrome浏览器性能分析工具和CSS动画使用GPU加速进行性能优化的解决方案。web

浏览器渲染流程

这是浏览器渲染引擎的处理过程:chrome


Alt pic

接收到文档后,渲染引擎会对HTML文档进行解析生成DOM树、对CSS文件进行解析生成CSSOM树;同时执行页面中的JavaScript代码;最终根据DOM树和CSSOM树,计算样式(Caluclate Style)生成渲染树,渲染树中,只会包含即将显示在页面中的元素及其样式信息(如head元素、display为hidden的元素就不会包含在渲染树中);根据渲染树须要进行布局(layout)来计算每一个元素在页面上的位置;数据库

接下来渲染引擎开始进行绘制(paint),这一步分为若干阶段:根据渲染树将每层(layer)的各个元素绘制,而后将绘制出的若干连续图像进行栅格化(Rasterization),最后将栅格化后的图像合成(composite)为要显示在屏幕上的图像。对每一层的绘制是由浏览器来完成的;最后的合成是由GPU来完成;而栅格化过程取决于浏览器的设置,chrome默认开启GPU栅格化,不然由CPU进行。浏览器

当首次将DOM树构建完成后,每次页面发生改变时进行进行的主要流程为:
缓存

Alt pic


其中CSS动画不会调用JavaScript,咱们知道,在渲染中主要消耗时间的是Layout/Reflow和Paint/Repaint的过程,所以要尽可能避免和减小这两个阶段的时间。安全

影响CSS动画性能的因素

这是一个CSS动画,控制一个方块的top、left属性实现平移。使用Chrome提供的浏览器性能分析工具分析动画的性能,打开浏览器开发者工具后,在标签中选择performance打开性能分析面板。在性能分析面板中对当前页面进行录制,录制结束后分析结果中能够查看页面在这段时间内的FPS、CPU占用等状况,在main中包含了浏览器的渲染流程,包括Scripting、Rendering、Painting等。性能优化

Alt pic

执行这个CSS动画时,不涉及JavaScript的调用;紫色部分是render,依次分别为Recaculate Style、Layout和Update Layer Tree;绿色部分为Painting,依次分别为Paint和Composite Layers。bash

在下面的面板中也能够查看当前时间段内各个阶段执行时间

Alt pic

Alt pic

more tools中的rendering也包含若干查看渲染有关的选项:

Alt pic

勾选paint flashing,页面上会以绿色方块显示须要重绘的区域,当前小方块进行了平移,所以须要重绘;勾选layer borders,会以黄色方框显示页面的分层状况,此时页面只有一个层,蓝色的线显示了tile的划分,它是一个layer中的分块;FPS meter能够显示页面的FPS、是否使用GPU进行栅格化过程和GPU显存使用状况,因为默认开启了GPU栅格化,GPU Raster显示为on:

Alt pic

more tools中的layers能够查看页面分层,以及每层的详细信息等:

Alt pic

经过对这些数据咱们能够对页面加载的性能瓶颈进行分析和针对性的优化。

使用GPU加速

浏览器的GPU加速功能是将须要进行动画的元素提高到一个独立的层(layer),这样就能够避免浏览器进行从新布局(Reflow)和绘制(Repaint),将原先的浏览器使用CPU绘制位图来实现的动画效果转为让GPU使用图层合成(composite)来实现,若是两张图层内部没有发生改变,浏览器就再也不进行布局和绘制,直接使用GPU的缓存来绘制每一个图层,GPU只负责将各个图层合成来实现动画,这就能够充分利用GPU的资源和优点,减轻CPU的负载,可使动画更流畅。经过改变两张图片之间的相对位置代替绘制一张图片的每一帧来实现动画,虽然视觉效果相同,但省去了许多绘制的时间。

为了让浏览器将动画元素提高到一个独立的层,可使用transform和opacity属性来实现动画,当设置了这两个属性之一时,浏览器会自动进行这一优化操做(透明度的变化能够经过GPU改变a通道来实现,不须要浏览器进行重绘)。对于上面的动画,能够改变transform来代替改变left和top属性:

这个动画进行分析,能够看到使用transform后浏览器为小方块单独设置了一个层,而且再也不触发浏览器更新样式:

Alt pic

Alt pic

若是动画并不须要对transform和opacity属性作出改变,可使用其余的方法强制浏览器为这些元素建立单独的层,好比设置一个没有效果的样式:transform:translateZ(0);这不会对元素的实际样式作出改变。但这是一种hack,规范的作法是使用will-change属性,设置它的值为须要作变换的属性,如will-change: left;浏览器就会知道left这个属性会发生变化,所以会开启硬件加速优化性能。

这是使用will-change属性的平移动画,一样也为小方块设置了单独的图层。

避免过分绘制

既然设置了will-change属性能够开启GPU加速,那么:

* {  will-change: all;}复制代码

看起来好像是一劳永逸的方法,但其实这反而会下降页面的性能,虽然硬件加速能够提升GPU的使用,但从layers中的信息能够看出,每一个层都须要消耗必定的内存,过多的内存占用也会形成性能的降低;过多的层传输到GPU的过程也会消耗必定的时间,此外也形成合成阶段的时间占用较长,所以并非独立的层越多越好。最好的作法是对那些可能动画的元素设置属性,并在动画结束后就移除这个属性。

SVG图表动画性能的优化

根据以上的分析,总结GPU实现动画的优缺点:

优势:

  • 利用了GPU合成图层实现动画,能够作到动画平滑、流畅

  • 动画合成工做在GPU线程,不会被CPU的js运行阻塞

缺点:

  • 绘图层必须传输到GPU,当图层较多时传输过程可能会致使渲染缓慢

  • 每一个复合层都须要消耗额外的内存,过多的内存可能致使浏览器的崩溃

  • 复合层合成须要更多的时间

对于通常的HTML的元素,遵循上述的方法就能够了,但有数大屏中的图表是使用SVG元素来绘制的,因为并非标准的DOM元素,Chrome并不能支持SVG元素的硬件加速,即便设置了transform、will-change等属性,单个的SVG元素也不能做为单独的层进行绘制。

从这个使用transform实现的SVG动画能够看到即便使用了transform,动画部分的页面仍然须要重绘。

Alt pic

对于下面这个有多个图表的页面,其中只有一个图表有动画,在动画过程当中,若是只有一个图层,那么须要将整个图层进行重绘,虽然如今Chrome已经能够智能选择最小的重绘区域进行增量绘制,但当图层较大时这样的判断也会形成必定的开销。所以能够考虑将有动画的图标单独放在一个图层中,其余没有动画的图表和页面是的其余元素仍然和背景在一个图层中:

Alt pic

分别对分层的和未分层的页面进行5次性能测试,将分析结果进行对比:

Alt pic

能够看出,分层后每帧动画绘制的总时间有明显降低,主要体如今绘制(painting)过程当中:其中paint时间的减小应该是由于每次重绘的图层面积只有图表区域,所以须要更少的时间来判断须要更新纹理的区域;composite layers时间的减小,应该主要是因为须要绘制的图层的减少,致使纹理上传GPU和调用OpenGL绘制接口的时间减小了;而rendering时间的增长缘由还须要进一步的调研。


在实际使用中,能够在某张图表须要动画时,设置SVG标签的will-change属性,将SVG元素提高到独立的层,来减小动画绘制时间;而图表没有动画时则不须要特别处理,避免过分绘制形成的内存占用增长和图层传输、合成时间的增长。

参考



免费体验云安全(易盾)内容安全、验证码等服务

更多网易技术、产品、运营经验分享请点击




相关文章:
【推荐】 关于数据库查询业务的几点思考

相关文章
相关标签/搜索