硬件加速

前言

谈起浏览器的硬件加速,想必大家都知道的一个技巧就是在用CSS3做动画时,给元素添加transform: translateZ(0)或者transform: translate3d(0, 0, 0)就会开启GPU的硬件加速,将本来应该是浏览器处理的动画效果转交给GPU处理,从而使得动画看起来更加顺畅,在移动端体验更好。本文将进一步探索其中的奥秘,例如哪些条件可以触发GPU硬件加速?硬件加速背后的工作原理是什么?是不是开启GPU硬件加速的动画应该越多越好?
首先让我们来看一个动画效果,通过CSS3的animation属性来实现让一个小球从坐到右移动200px的距离。现在有两种实现方式:

第一种方法通过改变该元素的top属性来实现:

.ball1{
  width:100px;
  height:100px;
  border-radius: 100px;
  background:red;
}
.ball1{
  animation:mymove 3s infinite linear;
  -moz-animation:mymove 3s infinite linear;
  -webkit-animation:mymove 3s infinite linear;
  -o-animation:mymove 3s infinite linear;
}

@keyframes mymove{
   from {top:0px;}
   to {top:200px;}
}

第二种方法通过translate来实现:

.ball1{
   animation:translateMove 3s infinite linear;
   -moz-animation:translateMove 3s infinite linear;
   -webkit-animation:translateMove 3s infinite linear;
   -o-animation:translateMove 3s infinite linear;
}
@keyframes translateMove {
   from {transform: translate3d(0,0,0);}
   to {transform: translate3d(0,200px,0)}
}

两种方式都能达到同样的效果,但浏览器在内部渲染的过程却大不相同。哪种实现方式更优?在回答这个问题之前,我们先来了解一下浏览器的渲染过程。

浏览器渲染过程

已知JS是单线程工作的,但是浏览器可以开启多个线程,渲染一个网页需要两个重要的线程来共同完成:Main Thread 主线程 Compositor Thread 合成器线程

主线程做的工作:

运行JS
计算 HTML 元素的 CSS 样式
布局页面
将元素绘制到一个或多个位图中
把这些位图交给 Compositor Thread 来处理

合成器线程做的工作:

通过 GPU 将位图绘制到屏幕上
通知主线程去更新页面中可见或即将可见的部分的位图
计算出页面中那些部分是可见的
计算出在滚动页面时候,页面中哪些部分是即将可见的
滚动页面时将相应位置的元素移动到可视区

在了解了这两个线程各自负责的部分之后,我们再来看浏览器的渲染过程。大体流程如下:

???
当我们通过某种方法引起浏览器的reflow时,需要重新经历style和layout阶段,导致浏览器重新计算页面中每个dom元素的尺寸及重新布局,伴随着重新进行repaint,这个过程是非常耗时的。为了把代价降到最低,当然最好只留下composite这一个步骤最好。假设当我们改变一个容器的样式时,影响的只是它自己,并且还无需重绘,直接通过在GPU中改变纹理的属性来改变样式,岂不是更好?

如何能使元素达到这个效果?就是让元素拥有自己的层(layer)。有了层的概念,让我们从层的概念再来看浏览器的渲染过程:

  1. 获取 DOM 并将其分割为多个层(RenderLayer)
  2. 将每个层栅格化,并独立的绘制进位图中
  3. 将这些位图作为纹理上传至 GPU
  4. 复合多个层来生成最终的屏幕图像(终极layer)

可以将这个过程理解为设计师的Photoshop文件。在ps源文件里,一个图像是由若干个图层相互叠加而展示出来的。分成多个图层的好处就是每个图层相对独立,修改方便,对单个图层的修改不会影响到页面上的其他图层。因此层(layer)存在的意义在于:用最小的代价来改变某个页面元素。可以将某个css动画或某个js交互效果抽离到一个单独的渲染层,来达到加速渲染的目的。

那么如何才能创建一个层呢?

  • 3d transform属性
  • backface-visibility为hidden的元素
  • 使用加速视频解码的 <video> 元素
  • 拥有 3D (WebGL) 上下文或加速的 2D 上下文的 <canvas> 元素
  • 混合插件(如 Flash)
  • 对 opacity、transform、fliter、backdrop-filter 应用了 animation 或者 transition(需要是 active 的 animation 或者 transition,当 animation 或者 transition 效果未开始或结束后,合成层也会失效)
  • will-change 设置为 opacity、transform、top、left、bottom、right(其中 top、left 等需要设置明确的定位属性,如 relative 等)
  • 元素有一个包含复合层的后代节点(换句话说,就是一个元素拥有一个子元素,该子元素在自己的层里)
  • 元素有一个 z-index 较低且包含一个复合层的兄弟元素(换句话说就是该元素在复合层上面渲染)

在webkit内核的浏览器中,如果有上述情况,就会创建一个独立的层(layer)。我们可以借助chrome浏览器开发者工具中的layers和rendering结合来查看页面中有哪些独立的层。

性能分析

现在回到文章开始的那个动画效果,让我们通过chrome的performance工具来看看具体的执行过程。(注:本次性能分析是将CPU性能将至原来的六分之一 模拟移动端的效果进行分析的。具体操作可将performance工具中的CPU选择6*slowdown)
通过改变top属性:

通过改变transform属性:

从上图可以看出,运动的元素如何没有独立的层,每一帧的绘制都需要经过不停的rendering和painting过程。

但硬件加速是把双刃剑,过渡的使用硬件加速会适得其反。其影响表现在:

  1. 内存。创建一个新的渲染层,需要消耗额外的内存和管理资源,如果渲染层的个数过多,很容易引起内存问题,这一点在移动端浏览器上尤为明显,可以引起电池耗电量的上升,降低电池的寿命。所以,一定要牢记不要让页面的每个元素都使用硬件加速,当且仅当需要的时候才为元素创建渲染层。
  2. 使用GPU渲染会影响字体的抗锯齿效果。文本在动画期间有可能会显示的模糊。

参考文档

  1. 无线性能优化:composite
  2. CSS动画及硬件加速
  3. Javascript高性能动画与页面渲染
  4. chrome渲染优化-层模型

原文地址:https://www.cnblogs.com/jlfw/p/11966222.html

时间: 2024-10-13 22:12:42

硬件加速的相关文章

CSS动画原理及硬件加速

一.图层 图层即层叠上下文,具体概念和应用大家可以看我之前转自张鑫旭大神博客的<CSS层叠上下文和层叠顺序>,这里我们简单复习一下产生层叠上下文的原因. 1.根层叠上下文 指的是页面根元素,也就是滚动条的默认的始作俑者<html>元素.这就是为什么,绝对定位元素在left/top等值定位的时候,如果没有其他定位元素限制,会相对浏览器窗口定位的原因. 2.定位元素与传统层叠上下文 对于包含有position:relative/position:absolute的定位元素,以及Fire

英特尔? 硬件加速执行管理器安装指南

介绍 本文将指导您安装英特尔? 硬件加速执行管理器(英特尔? HAXM),这是一款可以使用英特尔? 虚拟化技术(VT)加快 Android* 开发速度的硬件辅助虚拟化引擎(管理程序). 前提条件 英特尔 HAXM 要求首先安装 Android* SDK (版本为 17 或更高). 更多信息,请访问 Android* 开发人员网站 ( http://developer.android.com/sdk /). 系统要求 硬件要求: 支持 VT-x.EM64T 和病毒防护 (XD) 功能的英特尔? 处

安卓创建硬件加速

Android Studio 1.0 已经放出来了,以后的Android平台开发激昂逐步从Eclipse向Android Studio迁移,为了能不落伍我也特意从Google下载了Android Studio的安装包,并且兴高采烈地创建了我的第一个android项目.但是当运行的时候就他么悲催了. emulator: ERROR: x86 emulation currently requires hardware acceleration! Please ensure Intel HAXM is

Android 图形与硬件加速

今天在研究Android-PullToRefresh的时候,突然发现 清单文件中有这么一句 android:hardwareAccelerated="true".以前没有见过,果断百度,发现原来是与硬件加速有关,参见google开发者文档>   说是从Android3.0 开始 ,Android的2D 管道线就被设计成支持硬件加速的了.硬加速使用GPU承担了所有在View的canvas上执行的绘制操作.同时这样的应用也会消耗更多的内存.   启用硬加速最简单的的方法是对整个应用启

Android硬件加速

概述 从Android 3.0开始(API L11),Android开始全面使用硬件加速来进行2D渲染,硬件加速是指Android中在View上进行绘制的图形图像都使用GPU来进行绘制,使用硬件加速,在大部分时候都让绘制更加流畅,但付出的代价是需要消耗更多的内存资源. 硬件加速在API L14之上是默认开启的,对于基本的View绘制,通过硬件加速可以增加绘图的流程性,但是要注意的是,并不是所有的2D图形绘制API都支持硬件加速. 通过开发者选项中的"强制进行GPU渲染",用户可以为全局

Linux 下的模拟器硬件加速

Intel 提供了一个叫HAXM 的虚拟硬件加速技术,全称为:Intel Hardware Accelerated Execution Manager. 只要你的 CPU 是 intel 的产品并且支持 VT(virtualization Technology)就可以使用 HAXM 技术将你的模拟器的速度提升至真机的水平.目前此技术支持苹果的 Mac 系统和 Windows 系统,但 Linux 平台不在此列. 要知道 Android 的编译环境 Google 首推 Linux 平台(64位的U

用CSS开启硬件加速来提高网站性能(转)

用CSS开启硬件加速来提高网站性能(转) 翻译文章,原文地址:http://blog.teamtreehouse.com/increase-your-sites-performance-with-hardware-accelerated-css. 你知道我们可以在浏览器中用css开启硬件加速,使GPU (Graphics Processing Unit) 发挥功能,从而提升性能吗? 现在大多数电脑的显卡都支持硬件加速.鉴于此,我们可以发挥GPU的力量,从而使我们的网站或应用表现的更为流畅. 在桌

Chromium硬件加速渲染的UI合成过程分析

在Chromium中,Render端和WebGL端绘制出来的UI最终是通过Browser端显示在屏幕上的.换句话说,就是Browser端负责合成Render端和WebGL端的UI.这涉及到不同OpenGL上下文之间的资源传递和同步问题.其中,资源传递问题通过Mailbox机制解决,同步问题通过Sync Point机制解决.本文接下来就分析Browser端合成Render端和WebGL端UI的过程. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! Rende

Chromium硬件加速渲染的GPU数据上传机制分析

在Chromium中,WebGL端.Render端和Browser端通过命令缓冲区将GPU命令发送给GPU进程执行.GPU命令携带的简单参数也通过命令缓冲区发送给GPU进程,但是复杂参数,例如纹理数据,有可能太大以致命令缓冲区无法容纳,因此需要通过其它机制传递给GPU进程.本文接下来就主要以纹理数据上传为例,分析WebGL端.Render端和Browser端将GPU命令数据传递给GPU进程的机制. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! WebGL

Chromium硬件加速渲染的OpenGL命令执行过程分析

在Chromium中,由于GPU进程的存在,WebGL端.Render端和Browser端的GPU命令是代理给GPU进程执行的.Chromium将它们要执行的GPU命令进行编码,然后写入到一个命令缓冲区中,最后传递给GPU进程.GPU进程从这个命令缓冲区读出GPU命令之后,就进行解码,然后调用对应的OpenGL函数.本文就详细分析WebGL端.Render端和Browser端执行GPU命令的过程. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! 在前面Ch