经典性能优化面试题: 从一个 Transform 动画引发的关于浏览器渲染的深度思考

发表于 3年以前  | 总阅读数:459 次

1 Transform动画

类似点击商品飞入购物车内的移动动画的需求大家应该也都遇到过或自己开发过。但是和 Absolute 相比, Transform 的实现有什么区别呢?

从上图看 Transform 实现和 Absolute 实现的动画似乎并没有什么区别,为了更好的观察两种实现的区别,我们打开浏览器的重绘开关来观察元素的重绘情况:

案例显示 Absolute 实现的元素在移动中一直处于重绘之中,而使用 Transform 的元素却没有重绘。看来 transform 并不会触发重绘操作。要了解其中的缘由就需要从浏览器的渲染说起了。

2 浏览器渲染

2.1 DOM树之后发生了什么?

我们都知道,浏览器请求到前端资源之后构建 DOM树CSSOM树,创建的 CSSOM树DOM树 组合成一个Render树,然后用于计算每个可见元素的布局,然后将其绘制到屏幕上。Render Tree 并非最终的数据。从 DOM 到浏览器的画面,中间还会经历许多的步骤,诸如 Render ObjectRenderLayerGraphics Layer

2.2 Render Object Tree

上文提到 CSSOMDOM 组合成 Render Tree,计算每个可见元素的布局。这个可见元素的界定和存储就是我们的新同学 Render Object 的工作。

DOM Tree 中每一个可视节点都与一个 Render Object 对应。Render Object 存储在称为渲染树的并行树结构中,所以我们可以简单的理解 Render Object Tree 就是 DOMCSSOM 的合成并剔除了不可视节点的产物。

生成Render Object 规则:

  1. DOM 树中的Document节点
  2. 可视节点[1]
  3. 某些情况下生成的匿名Render Object 对象[2]

[1] 不可视节点

诸如 meta, head, script 等没有可视意义的节点。display: none; 的节点(注意 visibility: hidden; 是可视的)

[2] 匿名Render Object

某些情况下浏览器会主动生成匿名 Render Object, 例如根据 CSS 规范,inline 元素只能包含 block元素或 inline 元素中的一种。如果包含多种,会自动创建一个匿名盒模型,这个盒模型也对应一个 Anonymous RenderObject

RenderObject 知道如何在画布上绘制 Node 的内容。它通过对 GraphicsContext 发出必要的绘制调用来实现。GraphicsContext 负责将像素写入位图,最终将其显示在屏幕上。在Chrome中,GraphicsContext 包装了我们的2D图形库Skia。

2.3 Render Layer

回想一下,网页的排版顺序是非常复杂的,有 z-index 的层级关系,也有 overflow 的包含,裁剪等关系。这种层叠关系 Render Object 中是无法体现的。所以就有 Render Layer 帮助浏览器去存储关于层的信息。

Render LayerRender Object 并非一一对应。共享相同坐标空间(例如受相同CSS变换影响的 Render Object 属于同一个 Render Layer。每个 Render Object 都直接或通过祖先 Render Object 间接与 Render Layer 关联。

RenderObject 关联 RenderLayer 的常见情况:

  • 页面的根对象。
  • 具有明确的CSS位置属性(relativeabsolute, transform)。
  • 是透明的 (opacity < 1)。
  • overflowalpha maskreflection属性。
  • 有一个CSS filter过滤器。
  • <canvas>2D / 3D上下文(WebGL)。
  • <video>元素。

2.4 Graphics Layer

浏览器将DOM分隔成多个 Render Layer 并栅格化,独立地绘制进位图中, 然后作为纹理上传到GPU进行复合。但是如果栅格化的 Render Layer 中包含视频,Web GL等高耗内容时,一个小小的更新就可能让浏览器遭遇性能瓶颈。

为了避免此种情况,浏览器会为特定的 RenderLayer 提供后端存储(Graphics Layer),对于这些操作,可以跳过 Reflow 和 Repaint,直接在 GPU 中进行 Composite(合成)。

每个 Graphics Layer (图形层,也叫合成层)都有一个 GraphicsContext 供关联的 RenderLayer 绘制。浏览器会在随后的过程中通过合成器GraphicsContext 的位图作为纹理上传到GPU中并合成到最终的屏幕图像中。既解放了主线程,也利用了GPU对图形处理的极大优势。

理论上所有的 Render Layer 都可以提升为 Graphics Layer,但实际上这样的做法会非常浪费内存等资源。目前满足以下条件的 Render Layer能拥有自己的Graphics Layer

  • 3D 或透视变换 (perspective, transform) CSS 属性。
  • 使用加速视频解码的元素。
  • 拥有 3D (WebGL) 上下文或加速的 2D 上下文的元素。
  • 混合插件(如 Flash)。
  • opacity 做 CSS 动画或使用一个transform变换动画的元素。
  • 拥有加速 CSS 过滤器(filter)的元素。
  • iframe或含有position: fixed的元素。

隐式合成

  • 元素有一个包含复合层的后代节点(换句话说,就是一个元素拥有一个子元素,该子元素在自己的层里)。
  • 元素有一个 z-index 较低且包含一个复合层的兄弟元素(换句话说就是该元素在复合层上面渲染)。

合成器

合成步骤与合成器是息息相关的。

Chrome的合成器是一个软件库,用于管理 Graphics Layer 树和协调框架生命周期。

渲染通常都发生在两个阶段:绘画和合成。在硬件加速架构中,合成是通过调用特定于平台的3D API(Windows上为D3D;其他任何地方为GL)在GPU上进行的。当页面通过合成器渲染时,其所有像素都通过GPU进程直接绘制到窗口的后缓冲区中。

合成器可以在每个合成层的基础上执行其他工作。例如,合成器负责在合成之前对每个合成层的位图应用必要的转换(由图层的CSS Transform属性指定)。此外,由于层的绘画与合成是分离的,因此使这些层之一无效只会导致仅重新绘画该层的内容并进行合成。

合成器的基本任务是从主线程中获取足够的信息,以响应将来的用户输入而独立生成帧,即使主线程很忙并且无法请求其他数据。

或许这就能解释为什么开发者偏爱transform了。

应用了transform动画的容器会被提升为Graphics Layer(合成层),针对合成层,合成器能在合成前使用GPU对纹理(上传的位图)进行处理,这样的操作也就导致了动画容器跳过了重排重绘的阶段,直接进行合成。且合成器是对主线程的数据的副本进行操作,即使主线程忙于其他JavaScript操作,合成器也不会被阻塞。

2.5 提升合成层

合成层优点:

  • 合成层的位图作为纹理交由 GPU 生成,GPU 处理图形计算快速。
  • 合成层作为独立层,当回流、重绘时不影响其他层。

既然合成层这么厉害,为什么不好好利用呢?聪明的开发者们很早之前就开始了实践。

2.5.1 transform: translateZ(0)

最早(低版本浏览器)开发者使用 transform: translateZ(0) 来欺骗浏览器(因为它将使用GPU计算透视失真(即使最终根本没有失真))达到提升图层的作用。

注释:这里有一个坑就是使用了transform的元素会创建包含块, 这会导致 position: fixed/absolute 会以该元素作为父元素。

2.5.2 backface-visibility: hidden

transform: translateZ(0)使元素在早期版本(现在不会了)的Chrome和Safari中闪烁,因此人们建议改为backface-visibility: hidden

2.5.3 will-change:

2016年3月,IOS9获得了 will-change 属性的支持,该属性会告知浏览器某个属性将有可能改变,浏览器可以推测性地应用优化以适应这些将来的变化。在这种情况下使用 will-change: transformwill-change: opacity,它将迫使该元素提升为合成层。

2.6 合理利用合成层这把双面剑

尽管合成层作为动画优化是一大利器,但是使用不当也会反受其害的。

2.6.1 创建开销

渲染分为两步:绘画和合成。绘画(JS,Style,Layout,Paint)都是在CPU上完成的,合成是在GPU上。但是从CPU到GPU的转换是需要一些前置工作的。

  • CPU将每个合成层绘制为单独的图像。
  • 准备图层数据(大小,偏移,不透明度等)。
  • 为动画准备着色器(如果适用)。
  • 将数据发送到GPU。

所以每一次提升为合成层和去除合成层的状态转变都是伴随着这些步骤的。具体消耗的资源也就和合成层本身的大小和层数息息相关。

2.6.2 层爆炸

如上所说,GPU会对上传的纹理进行缓存管理,以便在以后的动画中重复使用,CPU和GPU之间的数据传输也需要一定的带宽,而CPU和GPU之间总线的带宽并不是无线的,这些因素导致合成层的出现可能会变得比较昂贵(特别是您的计算机的资源比较匮乏的时候)。

例如一张320x240 px的纯色图片,如果该图片是JPG(RGB)则占用320 × 240 × 3 = 230,400 bytes计算机内存,而如果是包含透明像素(PNG,RGBA)则需要使用320 × 240 × 4 = 307,200 bytes的内存。

不管是内存占用还是上传时的带宽都是有一定影响的。

其中我们将固有的合成原因(例如,具有3D变换的图层)称为“直接”合成原因。加上隐式合成原因,合成层的数量很容易脱离开发者的控制,资源大量占用进而导致性能表现不佳反而让人失望。这就是层爆炸问题。浏览器为了防止由于在直接合成原因的图层上放置许多元素时发生“图层爆炸”,会将多个Render Layers与直接合成原因的Render Layer重叠,然后将它们“挤压”到单个后备存储中。尽管浏览器有一定的优化手段(层压缩),但是合理提升层数量减轻设备的负担也是我们要去考虑的。

2.6.3 管理合成层

通过devtools我们能很直观的了解到页面的合成层的数量和占用的内存大小等。打开控制台,按住SHIFT+ Command + P打开搜索界面,输入show Layer,点击打开Layer面板。

第二张图片左侧都是一个合成层,右下角显示了当前合成层的合成原因及占用内存大小等信息。

1 . 减少合成层层数

最直观的办法当然就是减少合成层的层数问题。这里就分为主动提升和隐式合成。主动提升当然需要开发者自己去斟酌使用主动提升的性价比。我们比较关注的隐式合成,如下:

A和B元素处于重叠的状态,如果此时给B元素是一个应用了合成层的元素(如canvas,iframe,video等)处于其上的A元素就会被动提升为合成层。这时你就要考虑A放在B上是否合理,或者用其他的方式代替这样不明智的设计。

2 . 减少合成层大小

左边的图片是直接使用了一张39KB的图片,而右边则是使用的400B的小图并加上transform:scale(...)放大到和最左边图片相同尺寸。

先缩减图片的widthheight然后进行transform:scale操作是一个很好的思路,虽然我们不会都使用纯色的图片,但在用户可接受范围以内可以进行尝试,以小范围的精度缺失换取整个页面的流畅体验。

3 参考文档

CSS GPU Animation: Doing It Right[1]

GPU Accelerated Compositing in Chrome[2]

浏览器渲染页面工作原理[3]

WEBKIT 渲染不可不知的这四棵树[4]

参考资料

[1]CSS GPU Animation: Doing It Right: https://www.smashingmagazine.com/2016/12/gpu-animation-doing-it-right/

[2]GPU Accelerated Compositing in Chrome: https://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome

[3]浏览器渲染页面工作原理: https://developer.mozilla.org/zh-CN/docs/Web/Performance/%E6%B5%8F%E8%A7%88%E5%99%A8%E6%B8%B2%E6%9F%93%E9%A1%B5%E9%9D%A2%E7%9A%84%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86

[4]WEBKIT 渲染不可不知的这四棵树: https://juejin.cn/post/6844903446391308301#heading-9

本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/5QcrXNkpiKDfoSVKYaSk6w

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237231次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8065次阅读
 目录