某站 banner 在 Firefox 上的渲染


某网站 20 年🍁秋季的 banner 设计的挺好看的,然而在 Firefox 上的实际动画渲染效果却一言难尽,所以自己尝试摸索了一下。

TL; DR

在禁用自动硬件加速情况下, Firefox在渲染这个 banner 的时候似乎没有使用 GPU 加速,使用<iframe>可以缓解这个问题。

Detail

测试环境:

  • 显卡: i7-6700HQ 核显
  • Firefox: 81.0.1 禁用自动硬件加速 (我笔记本的硬件加速有些驱动相关的问题)
  • Chrome: 86.0.4240.75

为了方便分析首先实现一个 banner,先把模板 HTML 部分写好,之后用 React 来实现动画效果。

最开始想去某网站前端看一下他们的一些动画效果参数,在 DOM 改变处下了断点,然而断下来的地方是混淆的 JS 代码。丢到 jsnice 解了混淆后勉强能看,然而转念一想此处 CSS 属性变化(主要指transform)应该只是一个线性变化,测一个极限值自己算要方便的多,实际测试中发现filter: blur有些不是线性变化的,取了几个点做了个拟合(别拟合了,还是点对点直线好用),效果差强人意。

框架弄完了来看一下当前的性能数据,在 Firefox 上开了个性能分析看到动画只有 8fps,和某网站首页动画的帧数 (7fps) 基本相同。这当中每次重绘的耗时都在 80-100ms。一次重绘如果需要 0.1s 的话,就算 DOM 属性计算这些步骤不耗时,浏览器一秒内最多也就能渲染 10 帧。

然后为了比较一些性能数据,我开了个 Chrome,我发现这个动画在 Chrome 上可以跑到 50 fps!

最开始我以为是合成层的处理方式不同导致的渲染效率不同,后来查了些资料,开了调试设置对比了一下,似乎并没有不同之处。之后我找到了一篇关于 CSS 性能优化的资料,里面提到有一些元素和 CSS 会触发 GPU 渲染。对照了一下某网站的实现,怀疑其中translate: rotate(0deg)这一项就是用来触发 GPU 加速的,虽然不知道为什么在 Firefox 上没有生效。在一些尝试后,我发现position: fixed;<iframe>可以在 Firefox 上触发加速,就像上面你看到的那样。这样大概能达到 26fps ,和最开始的 8fps 相比好了很多了。

虽然和 Chrome 相比还有差距,但是我最近没什么空深究这个问题,准备暂时就这样搁置了。

Refer

CSS 硬件加速的好与坏: 一些有用的测试方法

CSS performance optimization