CSS 绘制时间和网页呈现权重

Colt McAnlis
Colt McAnlis

简介

如果您经常了解浏览器的工作原理等信息,那么您应该已经知道,最近的一些优秀文章详细介绍了 Chrome 的 GPU 加速渲染程序/合成操作。首先,Chrome 中的加速渲染:层模型简要介绍了 Chrome 如何使用层概念来绘制网页;如需深入了解,请参阅 Chrome 中的 GPU 加速合成,了解 Chrome 如何使用这些层以及 GPU 来渲染网页。

哲学问题

在花费大量时间编写用于 3D 目的的软件光栅化程序后,我发现一些 CSS 属性在绘制网页时应该会表现出不同的效果。例如,将小图片光栅化到屏幕上是一种完全不同的算法操作,在任意形状上绘制阴影。因此,问题变成了:不同的 CSS 属性如何影响网页的呈现权重?

我的目标是按绘制时间对大量 CSS 属性/值进行分类,以便我们了解哪些类型的 CSS 属性的效果比其他属性/值更高。为此,我用胶带和泡泡糖编写了一些自动化脚本,尝试为 CSS 绘制时间添加数字可见性,其运作方式如下:

  • 生成一组单独的 HTML 网页;每个网页包含一个 DOM 元素,以及附加到该元素的一些 CSS 属性排列组合。
  • 针对每个页面运行一些自动化脚本,脚本将:
    • 启动Chrome
    • 加载网页
    • 为网页生成 Skia Picture
    • 通过 Skia Benchmark 运行拍摄的每张 Skia 图片,以获取时间
  • 转储所有时间,并惊叹于这些数字。(这一点很重要…)

采用这种设置后,我们会生成一组 HTML 网页,其中每个网页都包含 CSS 属性和值的独特排列组合;例如,下面是两个 HTML 文件:

<style>
#example1 {
    background: url(foo.png) top left / 50% 60%;
    padding: 20px; 
    margin-top: 10px;
    margin-right: 20px; 
    text-align: center;
}
</style>
<div id="example1">WOAH</div>

还有一个更复杂的

<style>
#example1 {
    background-color:#eee;
    box-shadow: 1px 2px 3px 4px black;
    border-radius: 50%;
    background: radial-gradient(circle closest-corner, white, black);
    padding: 20px; 
    margin-top: 10px;
    margin-right: 20px; 
    text-align: center;
}
</style>
<div id="example1">WOAH</div>

下面是上个示例的变体,其中我们仅更改径向渐变值:

<style>
#example1 
{
    background-color:#eee;
    box-shadow: 1px 2px 3px 4px black;
    border-radius: 50%;
    background: radial-gradient(farthest-side, white, black);
    padding: 20px; 
    margin-top: 10px;
    margin-right: 20px; 
    text-align: center;
}
</style>
<div id="example1" style="padding: 20px; margin-top: 10px;margin-right: 20px; text-align: center;">WOAH</div>

然后,每个网页都会加载到一个新的 Chrome 实例中(以确保时间不会因网页重新加载中的任何过时状态而偏向),并获取 Skia 图片 (*.SKP) 以评估用于绘制网页的 Skia 命令。为每个 HTML 文件生成 SKP 文件后,我们会再运行一批作业,通过 Skia Benchmark 应用(基于 Skia 源代码构建)推送 *.SKP 文件,该应用会输出渲染该网页的平均时间。

评估数据

现在,我们已经能够大致了解一组 CSS 属性的绘制所需时间。或者,我们可以开始按绘制性能对 CSS 属性进行排序。下面是一个使用 Chrome 27 Beta 版生成的大型图表,显示了此进程中的完整时间数据集。请注意,随着时间的推移,Chrome 的速度会越来越快,因此所有数据都可能会发生变化。

测试中所有排列的时间

每个垂直条代表使用单个 CSS 属性组合的页面的绘制时间(放大 100 倍;此图表的真实比例值为 0,1.56 毫秒)。有很多漂亮的线条,但以这种形式显示这些数据没有什么用处;我们需要进行一些数据挖掘,才能发现有用的趋势。

首先,我们发现某些 CSS 属性的渲染开销比其他属性高得多。例如,在 DOM 元素上绘制阴影涉及使用样条和其他各种不良内容执行多遍操作,而不透明度应更容易渲染。

绘制仅具有 1 个 CSS 属性的元素所需的时间

其次,更有趣的是,CSS 属性的组合绘制时间可能会比各个部分的总和还要长。从观察者的角度来看,这有点奇怪,我们预计 A+B = C,而不是 2.2C。例如,添加 box-shadowborder-radius-stroke

测试中所有排列的计时

这一点真正有意思的是,它不仅仅是 box-shadow 属性本身,而是具体的值排列例如,下面显示了 box-shadow : 50%border-radius 的分组,其中包含值变体。

测试中所有排列的计时

看看数据,这个过程会持续一段时间。其中存在许多各种奇怪的组合,我的测试套件几乎不会触及它们;还有大量的测试和组合可能会产生有趣的结果

查找页面呈现权重

凭借跟踪网页上每个元素的呈现时间的功能,开发者可以开始评估其网页呈现权重,以及它对网站响应能力的影响。以下是几条入门提示

  1. 在 Chrome 开发者工具中使用 Chrome 的连续绘制模式,了解哪些 CSS 属性会导致性能开销。
  2. 将 CSS 审核纳入现有的代码审核流程,以发现性能问题 在 CSS 中查找已知会增加开销的用法,例如渐变和阴影。问问自己,我这里真的需要这些信息吗?
  3. 如果不确定,请务必选择性能更好的选项。用户可能不会记得列的边距宽度,但会记得访问您网站时的感受。

结语

这项实验最有趣的一点是,随着每个 Chrome 版本的发布,这些时间将继续发生变化(希望越来越快 ;) 浏览器软件是一个不断变化的领域。今天速度慢,明天就可能很快。您可以从本文中了解到,避免在已包含 border-radius:5 的元素中添加 box-shadow: 1px 2px 3px 4px不过,更有价值的结论应该是,CSS 属性会直接影响页面绘制时间。

参考