Base64 编码和性能,第 2 部分

Posted YITA90

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Base64 编码和性能,第 2 部分相关的知识,希望对你有一定的参考价值。

原文链接: https://csswizardry.com/2017/02/base64-encoding-and-performance-part-2/

这是这篇文章的第 2 部分。阅读第 1 部分

阅读这篇文章之前我会默认你已经阅读过第一部分。如果没有,我建议你先去阅读一下第一部分。


在样式表中插入 Base64 编码的内容资源(主要是图片)引起争议之后,我决定收集一些数据。
我做了一个简单的测试,针对 “传统” 方式和 Base64 方式,资源加载的时间进行对比。

测试,使它公平

创建两个简单的 html 文件,用一张背景图像铺满整个页面。第一个使用常规编写方式,第二个是 Base64 编码方式:

常规
Base64 编码

源图像是我的朋友艾希莉拍摄的。我把它调整为 1440×900 像素,保存为渐进式 JPEG 格式,并进行了优化和压缩处理,然后采用 Base64 编码版本:

harryroberts in ~/Sites/csswizardry.net/demos/base64 on (gh-pages)
» base64 -i masthead.jpg -o masthead.txt

对图片进行了适当的优化调整,使得 Base64 版本与我们常规的图片基本上差不多大。

创建两份样式表:

* 
  margin:  0;
  padding: 0;
  box-sizing: border-box;


.masthead 
  height: 100vh;
  background-image: url("[masthead.jpg|<data URI>]");
  background-size: cover;

文件准备好后,我就将其托管在一个网站上,这样我们就可以测试网络及其他可能存在的潜在因素对于加载速度的影响。

打开 Chrome 浏览器,关闭了之前打开的其他页面。

找到 Chrome 的 Timeline 选项卡,开始测试。过程记录如下:

  1. 禁用缓存。
  2. 清除之前遗留的时间线信息。
  3. 刷新页面并记录网络和时间线活动。
  4. 完全丢弃任何有关 DNS 或 TCP 请求连接的结果(我不希望记录受任何不相关网络活动)。
  5. 记录 DOMContentLoaded,Load,First Paint, Parse Stylesheet 和 Image Decode 运行时间。
  6. 清除数据后,重复前五步。
  7. 选出每次测量的中位数(中位数是正确的平均值)。
  8. 对于 Base64 版本执行相同操作。
  9. 在移动设备再次进行测试。(最终,我收集四组数据:电脑端 Base64 和 非 Base64,移动端 Base64 和 非 Base64 [^平台])。

第 4 点是一个非常重要的步骤:任何请求链接都会使结果发生偏差,出现矛盾:我只保留绝对零开销的结果。

移动设备测试

然后,我通过将 CPU 调节 3× 来模拟中档移动设备,网络限制为 Regular 2G,在移动端做了多次测试。

您可以查看 我在 Google 表格上收集的所有数据(所有数字以毫秒为单位)。数据的质量和一致性令我震惊:几乎没有出现统计学异常值。

我们先暂时忽略图像数据预加载的问题(稍后再讨论 )。电脑和手机的数据是不同的表格(见表格底部的 Tab 标签)。

一些见解

数据分析起来很容易,并且证实了我很多的猜想。你可以自己分析数据的情况,也可以参考我从中提取的重要信息:

  • 在 Desktop 和 Mobile 两种方法之间,DOMContentLoaded 加载情况没有很大变化。说明这里没有 “更好的选择”。
  • 这两种方法的Load 事件在 Mobile 上是相近的,但 Desktop Base64 是 2.02× 倍更慢(常规:236ms,Base64:476ms)。Base64 较慢。
  • 如果全部使用 Base64 编码,解析样式表的速度会慢得多。在 Desktop 上,解析速度慢 10 倍多。在 Mobile 上,解析速度慢 32 倍。Base64 看起来更慢。
  • 在 Desktop 上,Base64 图像解码比常规图像快 1.23 倍。Base64 更快。
  • … 但是在移动的时候,常规图像比 Base64 解码快 2.05 倍。Base64 较慢。
  • 首次渲染是衡量性能好坏的一个关键性指标:它告诉了我们用户什么时候开始看到某些东西。在 Desktop 上,常规图像 “首次渲染” 发生在 280ms,但 Base64 发生在 629ms:Base64 慢 2.25× 倍 , Base64 更慢。
  • Mobile 上,常规图像 首次渲染为 774ms,Base64 为 7950ms。Base64 慢了 10.27 倍。换句话说,常规图像开始在 1 秒以下展示,而 Base64 直到几乎 8 秒才开始展示。Base64 性能显着降低。

在所有这些指标中,我们有了一个显而易见的赢家:几乎所有的东西,在两个不同平台上,如果我们使用 Base64,都会更慢。我们测试结果幅度差距过大,几乎可以不用考虑低性能设备,或网络原因带给我们的测试结果误差:样式表解析 慢 32 倍 和 首屏渲染 慢 10.27 倍

第三种方法

加载图片的一个常见的问题是它下载的“瀑布流效果”:我们必须下载 HTML,然后请求 CSS 然后请求一个图片,这是一个非常同步的过程。Base64 具有理论上的优势,提供了一种更加并发的下载资源的方法,加载 CSS 同时加载图片(实际上没有优势,因为虽然它们都一起出现,但是它们都延迟了)。

其实,我们有一种可以实现这种并行化的方式,不用将我们所有的图片都加到样式表中。可以预先加载,而不是将图片作为一个迟来的资源,就像这样:

<link rel="preload" href="masthead.jpg" as="image" />

我做了另一个演示页面:

预加载图片

通过将此标签放在 HTML 中的 head 部分,我们实际上可以告诉 HTML 去下载图片,而不用等 CSS 去通知。这意味着,我们抛弃了如下的请求链:

|-- HTML --|                                   |
           |- CSS -|                           |
                   |---------- IMAGE ----------|
                                               |

而拥有一个这样的:

|-- HTML --|                           |
           |---------- IMAGE ----------|
           |- CSS -|                   |
                                       |

注意 a)加载速度更快 b)图像如何在 CSS 文件之前开始下载。预加载可以有效避免我们页面加载出来了,但图片资源却没有加载。

我决定制作一个使用常规图片的页面,不用 CSS 请求它,而是预加载:

<link rel="preload" href="masthead.jpg" as="image" />

<title>Preloaded Image</title>

<link rel="stylesheet" href="image.css" />

我没有注意到这个测试用例有很大的改进,预加载在这里不是很有用:我已经有这么短的请求链,我没有从重新排序中得到任何好处。但是,如果我们有一个需要加载很多资源的页面,那么预加载就会为页面带来提升。其实,我在我的主页上使用它来预先加载了masthead图片:这些资源通常会很晚才会被请求,但这种方式提前加载,会在展示效果上有重大变化。

我注意到的一件非常有趣的事情,就是解码时间。在 Mobile 上,图像在 25ms 内解码,而 Desktop 却是 36.57ms。

  • 在 Desktop 上,预先加载的图像在移动解码上比预载图像快 1.46 倍
  • Mobile 上的非预载图像比在 Mobile 上的预载图像速度更快了 3.53 倍

我不知道为什么会发生这种情况,但是如果我做了一个大胆的猜测:我想象图像在实际需要之前不会被解码,所以在实际需要必须解码之前只是一堆字节,这个过程会更快的工作吗?谁知道这个问题的答案,请告诉我!

我学到的一些有趣的事情

  • 渐进式 JPEG 解码比标准型 JPEG 慢。我期望可以将渐进式 JPEG 放在一起,渐进式 JPEG 在视觉上性能更好。可是,解码渐进 JPEG 要比标准型要多大约 3.3× 倍时间。(尽管如此,我仍然建议使用渐进式,因为他们在视觉感觉上,比标准型快得多)
  • Base64 图像解码是一次性的,而常规图像解码可分多次。我假设这是因为数据 URI 无法解码,除非它是完整的,而部分 JPEG 数据可以…?

改进测试方法

尽管我非常确认我的测试是尽可能不受潜在因素影响,是公平的,但有时间的时候,我希望我可以做得更好。(今天周末,我们继续…):

  • 在真实设备上测试 我使用 DevTools 限制了 CPU 和网速,但是在真实设备上运行这些测试,毫无疑问效果会更好。
  • 在 Mobile 上使用更合适的图像。为了尽可能的保证测试前提的一致性,我在电脑端和移动端使用了完全相同图片。事实上,Mobile 只是真正模拟降低的设备和网络能力,而不是用较小的屏幕或资源运行。实际,我们应该为小的设备提供小一点的图像(在尺寸和文件大小上)。但我并没有。我加载了完全相同的文件在完全相同的窗口,只是调整了网速和 CPU。
  • 测试一个更真实的项目。再次提示,这些只是实验室的条件。正如我在预载时指出的那样,这不是那种真实的开发环境。在同样的情况下,在分析非测试条件下的示例,结果可能会不同。

这就是我针对 Base64 的性能影响分析的两篇文章。有点像是在确认我们已经知道的常识,但通过一些数字一步一步分析,效果会更好,在低功率连接和设备上测试也尤为重要。Base64 在性能上不占优势。

[^平台]在这里补充一下:我只是针对我的笔记本电脑和模拟移动设备进行了测试,并没有区分屏幕大小。

以上是关于Base64 编码和性能,第 2 部分的主要内容,如果未能解决你的问题,请参考以下文章

检测base64编码

关于base64编码的原理及实现

Python 标准类库-因特网数据处理之Base64数据编码

用base64编码图像有啥效果?

python标准模块介绍 -Base64: Base64, Base85等数据编码

base64用法和使用场景