Brotli的实际效果

建立快速网站的一个更基本的规则是优化你的资产,而在HTML、CSS和JS等文本内容方面,我们正在谈论_压缩_。

网络上事实上的文本压缩是Gzip,大约80%的压缩响应赞成该算法,其余20%使用更新的_Brotli_。

当然,这个100%的总数只衡量实际被压缩的可压缩响应–仍有数百万的资源可以或应该被压缩但没有被压缩。关于这些数字的更详细的分类,请参见《网络年鉴》的压缩网络年鉴》的章节。

Gzip是非常有效的。莎士比亚的全部作品在纯文本格式下重达5.3MB;经过Gzip(压缩级别6),这个数字下降到1.9MB。这意味着文件大小减少了2.8倍,而数据的损失为零。很好!

对我们来说更好的是,Gzip有利于重复–在一个文本文件中发现的重复字符串越多,Gzip就越有效。这对网络来说是个好消息,因为HTML、CSS和JS有非常一致和重复的语法。

但是,虽然Gzip非常有效,但它很老;它在1992年发布(这当然有助于解释它的普遍性)。21年后,在2013年,谷歌推出了Brotli,一种新的算法,声称比Gzip有更大的改进!这就是Gzip。同样是5.2MB的莎士比亚汇编,用Brotli(压缩级别6)压缩后,就降到了1.7MB,文件大小减少了3.1倍。更漂亮!

使用Paul Calvano的 Gzip和Brotli压缩级别估计器!例如,ReactDOM,用最大级别的Brotli压缩(11)比用最大级别的Gzip压缩(9)要小27%。

在所有的压缩级别中,Brotli在压缩ReactDom时总是优于Gzip。在Brotli的最大设置下,它比Gzip要有效27%。

纯粹就事论事,我的一个客户从Gzip转移到Brotli后,文件大小的中位数节省了31%。

因此,在过去的几年里,我和其他像我一样的性能工程师,一直在建议我们的客户从Gzip转到Brotli。

浏览器支持。 一个简短的插曲。虽然Gzip被广泛支持,以至于Can I Use甚至没有列出它的表格(这个HTTP头实际上在所有的浏览器中都被支持(自IE6+,Firefox 2+,Chrome 1+等)),但Brotli目前在撰写本文时享有93.17%的全球支持,这是很巨大的这就是说,如果你是一个具有合理规模的网站,为超过6%的客户提供未压缩的资源可能会让你不太高兴。那么,你很幸运。客户端宣传他们对特定算法的支持的方式是完全渐进的,所以不能接受Brotli的用户将简单地退回到Gzip。稍后会有更多关于这方面的内容。

在大多数情况下,特别是如果你正在使用CDN,启用Brotli应该只是一个开关的轻弹。在Cloudflare,这当然很简单,我通过它来运行CSS Wizardry。然而,在过去的几年里,我的一些客户就没有这么幸运了。他们要么是在运行自己的基础设施,在各处安装和部署Brotli被证明是不容易的,要么是他们使用的CDN对新算法没有现成的支持。

在我们无法启用Brotli的情况下,我们总是在想如果……所以,最后我决定尝试量化这个问题:我们转向Brotli有多重要?

更小不一定意味着更快

通常情况下,是的!将文件变小会使其到达目的地。一般来说,把文件变小会使它更快到达。但是,比如说,把一个文件缩小20%,并不会使它提前20%到达。这是因为文件大小只是网络性能的一个方面,无论文件大小是多少,资源仍然被置于许多其他因素和常量之上–延迟、丢包等等。换句话说,文件大小的节省可以帮助你把数据塞进更低的带宽,但如果你有延迟限制,那些公认的较少的数据块到达的速度不会改变。

TCP、数据包和往返旅行

对于文件如何从服务器传输到客户端,我们需要看一下TCP。当我们从一个服务器上收到一个文件时,我们并不是一次就能得到整个文件。HTTP所依托的TCP将文件分割成若干段,或称_数据包_。这些数据包被分批、按顺序地发送至客户端。在下一个系列的数据包被传送之前,它们都会被确认,直到客户端拥有所有的数据包,没有一个数据包留在服务器上,而客户端可以将它们重新组合成我们可能认识到的一个文件。每批数据包在一次往返中被发送。

每个新的TCP连接没有办法知道它目前有多少带宽可用,也不知道连接的可靠性如何(即丢包)。如果服务器试图在一个只有一兆容量的连接上发送一兆的数据包,它将会淹没这个连接并导致拥堵。相反,如果它试图在一个只有一兆的连接上发送一兆的数据,它就不能获得充分的利用,大量的容量就会被浪费。

为了解决这个小难题,TCP利用了一种被称为_慢速启动_的机制。 每个新的TCP连接在其第一次往返旅行中只能发送10个数据包。10个TCP段相当于大约14KB的数据。如果这10个段成功到达,下一次往返将携带20个数据包,然后是40个、80个、160个,以此类推。这种指数式的增长一直持续到两种情况之一发生。

  1. 我们遭遇数据包丢失,这时服务器会将最后尝试的数据包数量减半并重试,或者。
  2. 我们的带宽达到极限,可以满负荷运行。

这个简单而优雅的策略在谨慎和乐观之间取得了平衡,并且适用于你的网络应用程序的每一个新的TCP连接。

简单地说:你在一个新的TCP连接上的初始带宽容量只有14KB左右。或者大约是未压缩的ReactDom的11.8%;Gzipped ReactDom的36.94%;或者Brotlied ReactDom的42.38%(都设置为最大压缩)。

等等。从11.8%到36.94%的飞跃是非常显著的!但从36.94%到42.38%的飞跃是不一样的。但从36.94%到42.38%的变化就不那么引人注目了。发生了什么事?

往返次数 TCP容量(KB) 累计传输(KB 转移的ReactDom由…
1 14 14
2 28 42 Gzip (37.904KB), Brotli (33.036KB)
3 56 98
4 112 210 未压缩 (118.656KB)
5 224 434

Gzipped和Brotlied版本的ReactDom都适合于同一个往返桶:只需两次往返就能传输完整的文件。如果所有的往返时间(RTT)都相当统一,这意味着Gzip和Brotli的传输时间在这里没有区别。

另一方面,未压缩的版本需要多花整整两个往返时间才能完全传输,特别是在高延迟的连接上,这可能是相当明显的。

我想说的是,这不仅仅是文件大小的问题,也是TCP、数据包和往返次数的问题。我们不只是想让文件变小,我们想让它们有意义地变小,让它们进入更低的往返次数。

这意味着,从理论上讲,要使Brotli比Gzip更有效,它需要能够更积极地压缩文件,以便使其低于往返阈值。我不确定它的效果如何……

值得注意的是,这个模型是相当积极的简化,还有无数的因素需要考虑:TCP连接是否是新的,它是否被用于其他方面,服务器端的优先权是否停止了传输,H/2流是否有独占的带宽权限?本节是一个比较学术性的评估,应该被看作是一个很好的跳板,但是可以考虑用Wireshark之类的东西对数据进行适当的分析,也可以阅读Barry Pollard在他的《14KB的魔力》中对14KB的法医分析。 关键资源和前14KB–回顾.

这条规则也只适用于全新的TCP连接,任何通过原始TCP连接获取的文件都不会受到慢速启动的影响。这提出了两个重要的观点。

  1. 这一点不需要重复:你需要 自我托管你的静态资产这是一个避免慢速启动惩罚的好方法,因为使用你自己的已经热起来的原点意味着你的数据包可以获得更大的带宽,这使我想到第二点。
  2. 随着指数式增长,你可以看到我们达到相对巨大的带宽有多快。我们使用或重复使用的连接越多,我们就能进一步增加容量,直到我们的顶峰。让我们看一下上表的延续…
往返次数 TCP容量(KB) 累积传输量(KB
1 14 14
2 28 42
3 56 98
4 112 210
5 224 434
6 448 882
7 896 1,778
8 1,792 3,570
9 3,584 7,154
10 7,168 14,322
20 7,340,032 14,680,050

在10次往返结束时,我们的TCP容量为7,168KB,已经累计传输了14,322KB。这对于休闲的网络浏览来说是绰绰有余的(也就是说,不是激流式的流传《权力的游戏》)。实际上,这里通常发生的情况是,在我们达到带宽的极限之前,我们最终加载了整个网页及其所有的子资源。换句话说,你的1Gbps1光纤线路不会让你的日常浏览感觉快很多,因为大部分的带宽甚至没有被使用。

通过20次往返,理论上我们达到了7.34GB的容量。

那么现实世界呢?

好吧,是的。这一切都变得有点理论化和学术化。我开始这整个思路是因为我想看看,现实中,Brotli对真正的网站可能有什么影响。

到目前为止的数据显示,没有压缩和Gzip之间的差异是巨大的,而Gzip和Brotli之间的差异则要小得多。这表明,虽然_从无到有_,从Gzip到Brotli的升级将是明显的,但从Gzip到Brotli的升级可能不那么令人印象深刻。

我选取了一些例子网站,我试着把这些网站作为一个很好的截面。

  • 相对知名的(最好是使用人们可以理解的演示),和/或。
  • 与测试相关并适合测试(即合理的大小(压缩更相关),并且不是主要由不可压缩的内容组成(例如,像YouTube)),和/或。
  • 不是所有的数十亿美元的公司(让我们也使用一些正常的案例研究)。

有了这些要求,我抓起了一些起源,开始测试。

我想保持测试的简单,所以我只抓取了。

  • 转移的数据,以及。
  • 第一批内容丰富的油漆(FCP)次数。
  • 没有压缩。
  • 用Gzip,和。
  • 使用Brotli。

FCP感觉是一个现实世界的通用指标,可以适用于任何网站,因为这就是人们在那里的目的–内容。也因为Paul Calvano这么说,而且他很聪明:根据我的经验,Brotli倾向于使FCP更快,特别是当关键的CSS/JS很大时。

运行测试

这里有一个有点肮脏的秘密。很多网络性能的案例研究–不是全部,而是很多–并不是基于改进,而是经常从相反的方面进行推断:速度减慢。例如,英国广播公司(BBC)说他们的网站每多花一秒钟就会损失10%的用户,这要比计算出1秒的速度会发生什么要简单得多。让一个网站变慢要容易得多,这就是为什么这么多人似乎都很擅长这个。

考虑到这一点,我不想找到Gzipped网站,然后尝试以某种方式将其Brotli下线。我从Brotli到Gzip,再到Gzip,再到没有,并测量每个选项的影响。

虽然我不能完全跳到LinkedIn的服务器上禁用Brotli,但我可以选择用不支持Brotli的浏览器来请求该网站。 虽然我不能完全在Chrome中禁用Brotli,但我可以向服务器隐藏Brotli被支持的事实。浏览器宣传其接受的压缩算法的方式是通过content-encoding 请求头,而使用WebPageTest,我可以定义我自己的压缩算法。很简单!

WebPageTest的高级功能允许我们设置自定义请求头。

  • 要完全禁用压缩:accept-encoding: randomstring
  • 禁用Brotli而使用Gzip:accept-encoding: gzip
  • 如果Brotli可用(并且浏览器支持它),则使用它:留空。

然后我可以通过检查响应中相应的(或没有)content-encoding 头来验证事情是否按计划进行。

调查结果

正如预期的那样,从什么都没有到Gzip有巨大的回报,但从Gzip到Brotli就不那么令人印象深刻了。原始数据可以在这个Google Sheet中找到,但我们主要关心的是。

  • Gzip大小的减少与什么都没有相比:减少73%。
  • Gzip对FCP的改进:减少23.305%。
  • Brotli对Gzip的大小减少:减少5.767%。
  • Brotli FCP的改进与Gzip相比:减少了3.462%。

所有数值都是中位数;”大小 “仅指HTML、CSS和JS。

Gzip使文件比完全不压缩的文件小72%,但Brotli只在此基础上为我们额外节省了5.7%。在FCP方面,与完全不使用任何东西相比,Gzip给我们带来了23%的改进,但Brotli只在此基础上为我们获得了额外的3.5%。

虽然结果似乎支持了这一理论,但我仍有一些方法可以改进测试。第一个方法是使用更大的样本量,另外两个方法我将在下面更全面地概述。

第一方与第三方的对比

在我的测试中,我全面禁用了Brotli,而不仅仅是针对第一方的来源。这意味着,我不是只测量目标使用Brotli的好处,也可能测量他们所有的第三方。只有当目标网站的关键路径上有第三方时,我们才会真正感兴趣,但这是值得记住的。

压缩级别

当我们谈论压缩时,我们经常在最佳情况下讨论它:9级Gzip和11级Brotli。然而,你的网络服务器不太可能以最理想的方式配置。Apache的默认Gzip压缩级别是6,但Nginx只设置为1。

禁用Brotli意味着我们回到了Gzip,考虑到我是如何测试这些网站的,我不能改变或影响任何配置或后备配置。我提到这个是因为当我们启用Brotli时,测试中的两个网站实际上变得更大了。对我来说,这表明他们的Gzip压缩级别被设置为比Brotli级别更高的值,使Gzip更有效。

压缩级别是一种权衡。理想情况下,你希望把所有东西都设置为最高值,然后就完事了,但这并不实际–在服务器上动态设置所花费的时间很可能会抵消压缩的好处。为了解决这个问题,我们有两个选择。

  1. 使用一个实用的压缩级别,在动态压缩资产时平衡速度和效果,或者。
  2. 上传预压缩的静态资产,其压缩级别要高得多,并在动态响应中使用第一个选项。

那又怎样?

从现实来看,Brotli比Gzip的好处似乎不大。

如果启用Brotli就像在你的CDN的管理面板上弹一个复选框那么简单,请现在就去做:支持范围足够广,回退很简单,即使是最小的改进也比没有好。

在可能的情况下,将预压缩的静态资产以最高的压缩设置上传到你的网络服务器上,而对任何动态的东西使用更中间的东西。如果你在Nginx上运行,请确保你没有使用他们可怜的默认压缩级别1。

然而,如果你面临着几周的工程、测试和部署工作,以使Brotli上线,不要太惊慌–只要确保你在所有可以压缩的东西上使用Gzip(这包括你的.ico.ttf 文件,如果你有的话)。

我想这个故事的简短版本是,如果你没有或不能启用Brotli,你不会错过什么。

  1. 你所得到的1Gbps实际上相当于0.125GBps。互联网公司将他们的虚假广告隐藏在众目睽睽之下。
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享