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 基准拍摄的每张 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 Picture (*.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 版本的运行时间都会有所变化(希望能够加快浏览器软件的演变程度)。今天的加载速度慢,明天可能会变快。您可以脱离本文,避免将 box-shadow: 1px 2px 3px 4px 放在已有 border-radius:5 的元素中。不过,更有价值的一点是,CSS 属性会直接影响网页绘制时间。

参考编号