CSS动画的性能分析和浏览器GPU加速
此文已由作者袁申授权网易云社区发布。
欢迎访问网易云社区,了解更多网易技术产品运营经验。
有数的数据大屏可以在一块屏幕上展示若干张不同的图表,以炫酷的方式展示各种业务数据。其中有些图表使用CSS实现了饼图轮播、地图标记点闪烁等动画,然而在一张大屏上同时显示了许多张图表时,持续的动画效果有时会出现掉帧、卡顿的情况,需要对动画性能进行优化。本文简单介绍了chrome浏览器性能分析工具和CSS动画使用GPU加速进行性能优化的解决方案。
浏览器渲染流程
这是浏览器渲染引擎的处理过程:
接收到文档后,渲染引擎会对HTML文档进行解析生成DOM树、对CSS文件进行解析生成CSSOM树;同时执行页面中的JavaScript代码;最终根据DOM树和CSSOM树,计算样式(Caluclate Style)生成渲染树,渲染树中,只会包含即将显示在页面中的元素及其样式信息(如head元素、display为hidden的元素就不会包含在渲染树中);根据渲染树需要进行布局(layout)来计算每个元素在页面上的位置;
接下来渲染引擎开始进行绘制(paint),这一步分为若干阶段:根据渲染树将每层(layer)的各个元素绘制,然后将绘制出的若干连续图像进行栅格化(Rasterization),最后将栅格化后的图像合成(composite)为要显示在屏幕上的图像。对每一层的绘制是由浏览器来完成的;最后的合成是由GPU来完成;而栅格化过程取决于浏览器的设置,chrome默认开启GPU栅格化,否则由CPU进行。
当首次将DOM树构建完成后,每次页面发生改变时进行进行的主要流程为:
其中CSS动画不会调用JavaScript,我们知道,在渲染中主要消耗时间的是Layout/Reflow和Paint/Repaint的过程,因此要尽量避免和减少这两个阶段的时间。
影响CSS动画性能的因素
这是一个CSS动画,控制一个方块的top、left属性实现平移。使用Chrome提供的浏览器性能分析工具分析动画的性能,打开浏览器开发者工具后,在标签中选择performance打开性能分析面板。在性能分析面板中对当前页面进行录制,录制结束后分析结果中可以查看页面在这段时间内的FPS、CPU占用等情况,在main中包含了浏览器的渲染流程,包括Scripting、Rendering、Painting等。
执行这个CSS动画时,不涉及JavaScript的调用;紫色部分是render,依次分别为Recaculate Style、Layout和Update Layer Tree;绿色部分为Painting,依次分别为Paint和Composite Layers。
在下面的面板中也可以查看当前时间段内各个阶段执行时间
more tools中的rendering也包含若干查看渲染有关的选项:
勾选paint flashing,页面上会以绿色方块显示需要重绘的区域,当前小方块进行了平移,因此需要重绘;勾选layer borders,会以黄色方框显示页面的分层情况,此时页面只有一个层,蓝色的线显示了tile的划分,它是一个layer中的分块;FPS meter可以显示页面的FPS、是否使用GPU进行栅格化过程和GPU显存使用情况,由于默认开启了GPU栅格化,GPU Raster显示为on:
more tools中的layers可以查看页面分层,以及每层的详细信息等:
通过对这些数据我们可以对页面加载的性能瓶颈进行分析和针对性的优化。
使用GPU加速
浏览器的GPU加速功能是将需要进行动画的元素提升到一个独立的层(layer),这样就可以避免浏览器进行重新布局(Reflow)和绘制(Repaint),将原先的浏览器使用CPU绘制位图来实现的动画效果转为让GPU使用图层合成(composite)来实现,如果两张图层内部没有发生改变,浏览器就不再进行布局和绘制,直接使用GPU的缓存来绘制每个图层,GPU只负责将各个图层合成来实现动画,这就可以充分利用GPU的资源和优势,减轻CPU的负载,可以使动画更流畅。通过改变两张图片之间的相对位置代替绘制一张图片的每一帧来实现动画,虽然视觉效果相同,但省去了许多绘制的时间。
为了让浏览器将动画元素提升到一个独立的层,可以使用transform和opacity属性来实现动画,当设置了这两个属性之一时,浏览器会自动进行这一优化操作(透明度的变化可以通过GPU改变a通道来实现,不需要浏览器进行重绘)。对于上面的动画,可以改变transform来代替改变left和top属性:
对这个动画进行分析,可以看到使用transform后浏览器为小方块单独设置了一个层,并且不再触发浏览器更新样式:
如果动画并不需要对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,动画部分的页面仍然需要重绘。
对于下面这个有多个图表的页面,其中只有一个图表有动画,在动画过程中,如果只有一个图层,那么需要将整个图层进行重绘,虽然现在Chrome已经可以智能选择最小的重绘区域进行增量绘制,但当图层较大时这样的判断也会造成一定的开销。因此可以考虑将有动画的图标单独放在一个图层中,其他没有动画的图表和页面是的其他元素仍然和背景在一个图层中:
分别对分层的和未分层的页面进行5次性能测试,将分析结果进行对比:
可以看出,分层后每帧动画绘制的总时间有明显下降,主要体现在绘制(painting)过程中:其中paint时间的减少应该是因为每次重绘的图层面积只有图表区域,因此需要更少的时间来判断需要更新纹理的区域;composite layers时间的减少,应该主要是由于需要绘制的图层的减小,导致纹理上传GPU和调用OpenGL绘制接口的时间减少了;而rendering时间的增加原因还需要进一步的调研。
在实际使用中,可以在某张图表需要动画时,设置SVG标签的will-change属性,将SVG元素提升到独立的层,来减少动画绘制时间;而图表没有动画时则不需要特别处理,避免过度绘制造成的内存占用增加和图层传输、合成时间的增加。
参考
更多网易技术、产品、运营经验分享请点击。
相关文章:
【推荐】 用script标签加载
CSS动画的性能分析和浏览器GPU加速的更多相关文章
- css动画属性性能
性能主要表现:流量.功耗与流畅度 在现有的前端动画体系中,通常有两种模式:JS动画与CSS3动画. JS动画是通过JS动态改写样式实现动画能力的一种方案,在PC端兼容低端浏览器中不失为一种推荐方案. ...
- CSS动画属性性能详细介绍
CSS动画属性会触发整个页面的重排relayout.重绘repaint.重组recomposite Paint通常是其中最花费性能的,尽可能避免使用触发paint的CSS动画属性,这也是为什么我们推荐 ...
- Android性能分析工具Profile GPU rendering详细介绍
如何在一个应用中追踪和定位性能问题,甚至在没有它的源代码的情况下?? “Profile GPU rendering”(GPU渲染分析),一款Android4.1所引入的工具.你可以在“设置”应用的“开 ...
- 盒子端 CSS 动画性能提升研究
不同于传统的 PC Web 或者是移动 WEB,在腾讯视频客厅盒子端,接大屏显示器(电视)下,许多能流畅运行于 PC 端.移动端的 Web 动画,受限于硬件水平,在盒子端的表现的往往不尽如人意. 基于 ...
- 前端性能优化之利用 Chrome Dev Tools 进行页面性能分析
背景 我们经常使用 Chrome Dev Tools 来开发调试,但是很少知道怎么利用它来分析页面性能,这篇文章,我将详细说明怎样利用 Chrome Dev Tools 进行页面性能分析及性能报告数据 ...
- GPU—加速数据科学工作流程
GPU-加速数据科学工作流程 GPU-ACCELERATE YOUR DATA SCIENCE WORKFLOWS 传统上,数据科学工作流程是缓慢而繁琐的,依赖于cpu来加载.过滤和操作数据,训练和部 ...
- 构建可扩展的GPU加速应用程序(NVIDIA HPC)
构建可扩展的GPU加速应用程序(NVIDIA HPC) 研究人员.科学家和开发人员正在通过加速NVIDIA GPU上的高性能计算(HPC)应用来推进科学发展,NVIDIA GPU具有处理当今最具挑战性 ...
- Android 常用的性能分析工具详解:GPU呈现模式, TraceView, Systrace, HirearchyViewer(转)
此篇将重点介绍几种常用的Android性能分析工具: 一.Logcat 日志 选取Tag=ActivityManager,可以粗略地知道界面Displaying的时间消耗.当我们打开一个Activit ...
- CSS动画与GPU
写在前面 满世界的动画性能优化技巧,例如: 只允许改变transform.opacity,其它属性不要动,避免重新计算布局(reflow) 对动画元素应用transform: translate3d( ...
随机推荐
- Canvas学习笔记——动画中的三角学
示例1,跟随鼠标的键头: 需要掌握一个重要的公式,这个方法返回从 x 轴到点 (x,y) 之间的角度 Math.atan2(dy,dx); 关键代码: function Arrow() { thi ...
- poj1125--Floyd
题解: 有N个股票经济人能够互相传递消息.他们之间存在一些单向的通信路径.如今有一个消息要由某个人開始传递给其它全部人.问应该由哪一个人来传递,才干在最短时间内让全部人都接收到消息. 显然,用Floy ...
- 如何使Htm页面使用IE9文档模式
修改Htm页面的方法之一是,在Head->Title下添加<META http-equiv="X-UA-Compatible" content="IE=9&q ...
- 【计蒜客2017NOIP模拟赛1】
D1T1 题面 题解:一开始以为傻题,旋转个坐标系就行了,结果光荣爆零~ 结果发现旋转坐标系后,由于多了一些虚点,锤子砸到虚点上了~gg [没有代码] D1T2 题面 题解:计算出每个边对答案的贡献即 ...
- javascript JS递归遍历对象 使用for(variable in object)或者叫for/in和forEach方式
1.递归遍历查找特定key值(ie9以下不支持forEach) 原文http://www.cnblogs.com/ae6623/p/5938560.html var obj = { first: &q ...
- 04-树4 是否同一棵二叉搜索树(25 point(s)) 【Tree】
04-树4 是否同一棵二叉搜索树(25 point(s)) 给定一个插入序列就可以唯一确定一棵二叉搜索树.然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到.例如分别按照序列{2, 1, 3}和 ...
- Ubuntu Linux系统环境变量配置文件【转】
本文转载自:https://my.oschina.net/qinlinwang/blog/30471 Ubuntu Linux系统环境变量配置文件: /etc/profile : 在登录时,操作系统 ...
- SDUT OJ 之 1571 《人品,有没有?》 字符串的处理问题
人品,有木有? Time Limit: 1000ms Memory limit: 32768K 有疑问?点这里^_^ 题目描述 新一届的山东理工大学ACM网络擂台赛就要开始啦!听说晋级的选手有机 ...
- Redis雪崩效应以及解决方案
缓存雪崩产生的原因 缓存雪崩通俗简单的理解就是:由于原有缓存失效(或者数据未加载到缓存中),新缓存未到期间(缓存正常从Redis中获取,如下图)所有原本应该访问缓存的请求都去查询数据库了,而对数据库C ...
- div遮罩弹框口
<html> <head> <meta http-equiv="Content-Type" content="text/html; char ...