使用 Pingdom 和 GTmetrix 改善性能感知

本文是关于构建示例应用程序(多图像库博客)以进行性能基准测试和优化的系列文章的一部分。 (在此处查看回购协议。)

在本文中,我们将使用我们在上一篇指南中介绍的工具分析我们的图库应用程序,并且我们将研究进一步提高其性能的可能方法。

根据上一篇文章,请设置 Ngrok 并通过它连接到本地托管的应用程序,或者在您自己的演示服务器上托管该应用程序。 这个静态 URL 将使我们能够使用 GTmetrix 和 Pingdom 工具等外部工具测试我们的应用程序。

我们去用 GTmetrix 扫描了我们的网站,看看我们如何改进它。 我们看到,结果虽然不是灾难性的糟糕,但仍有改进的余地。

第一个选项卡 — PageSpeed — 包含 Google 的推荐列表。 PageSpeed 选项卡下的第一项——有关一致 URL 的警告——与我们的应用程序随机输出图像有关,因此我们将跳过该项目。 接下来我们可以做的是浏览器缓存。

浏览器缓存

我们看到有一个 main.css 需要它的文件 Expires 标头集,图库中的图像需要同样的东西。 现在,这些静态文件的第一个想法是在我们的 Nginx 配置中设置它:

location ~* .(?:ico|css|js|gif|jpe?g|png)$ {
    expires 14d;
}

我们可以简单地将其放入我们的 server block 交给 Nginx 对不对?

好吧,不是真的。 这将处理我们的静态文件,例如 CSS,但是 /raw 我们被警告的图像并不是那么静态。 所以我们 Nginx 配置中的这个片段不会那么容易地完全解决这个问题。 对于我们的图像,我们有一个实际的控制器可以动态创建这些图像,因此如果我们可以在控制器中就地设置响应标头,那将是理想的选择。 由于某些原因,Glide 没有正确设置这些。

也许我们可以设置我们的 Nginx 指令以包含 raw 资源,但我们认为控制器方法更具前瞻性。 这是因为我们不确定其他哪些内容可能会以 raw 后缀最终 – 可能是一些视频,甚至是音频文件。

于是,我们开了 /src/ImageController.php 在我们的图片库应用程序中,并将这两行放在我们的 serveImageAction()就在那行之前 return $response:

// cache for 2 weeks
$response->setSharedMaxAge(1209600);
// (optional) set a custom Cache-Control directive
$response->headers->addCacheControlDirective('must-revalidate', true);

这将通过添加适当的 Cache ControlExpires 标题。

Symfony 有更全面的响应缓存选项,如此处所述。

重启 Nginx 后,我们在 GTmetrix 中重新测试了我们的应用程序,你瞧:

压缩

接下来,GTmetrix 向我们发出了有关资源大小和压缩的警告:

在生产中,这是一件微不足道的事情,在这种特殊情况下对此进行改进不会产生太大影响,只需要几千字节的空间。 但是,由于这些指南在这里是为了展示其他更重要的应用程序的方法,因此我们也将介绍这一改进。

图像可以提前优化,但由于这些是使用 Glide 创建的动态图像,我们在另一篇文章中对此进行了介绍,因此我们不会这样做。 事实上,Glide 提供了设置图像质量的方法。 但有时我们不会使用 Glide 来处理我们的图像,所以我们将首先在这里尝试另一种方法。

在我们的 Nginx 内部 server 块,我们将添加几行指示 Nginx 压缩我们的内容:

gzip on;
gzip_disable "msie6";

gzip_vary on;
gzip_proxied any;
gzip_comp_level 9;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/jpeg;

对这些设置中的每一个的解释超出了本文的范围。 Nginx 网站上对这些项目中的每一项进行了解释,但值得讨论的一件事是 gzip_comp_level.

对于压缩,常识是需要权衡取舍。 通过缩小文件大小,我们获得了一些网络带宽,但随后我们在服务器 CPU 周期中损失了一些资源,这些周期需要在每次请求时不断 gzip 我们的资源。 或者正如这篇 Cloudflare 博客文章(我们稍后会谈到)所说:

压缩速度和传输速度之间存在权衡。 如果您可以比实际传输字节数更快地减少必须传输的字节数,那么提高压缩率只会对提高压缩率有益。

这就是为什么人们很少设置 gzip_comp_level 最多 9 个,就像我们所做的那样。 他们通常满足于 6 之类的东西。这样,访问者仍然可以获得压缩资源,但 CPU 仍然不会承受很大的压力,尤其是在流量高峰期间。

但是我们不会遵循这个常见的建议,原因有两个:首先,在生产中,我们很可能会在 CDN 上部署我们的应用程序,这将完全消除我们服务器的负担,其次,即使我们不使用在 CDN 中,我们将使用页面缓存,因此我们的服务器完成的 gzip 压缩——希望——每个资源只完成一次。 而且,随着我们的浏览器缓存完全开启,即使是这些缓存的 gzip 资源也不会被如此频繁地请求。

所以,这就是设置我们的理由 gzip_comp_level 到 9,但如果我们不打算使用页面/HTTP 缓存,我们可能会将其设置为较小的数字。

通过这样做,我们能够改进我们的 gzip 结果:

但是,我们无法通过图像实现同样的改进。 所以,我们回到 Glide 文档,找到了如何控制图像的质量:在我们的 serveImageAction() 在我们的里面 ImageController,我们找到了这一行:

$cachePath = $glide->getGlide()->makeImage($file, ['w' => $size]);

我们在 makeImage() 第二个数组参数:

$cachePath = $glide->getGlide()->makeImage($file, ['w' => $size, 'q' => 60]);

我们不想将图像质量设置得比这低,因为它看起来不太好:

然后我们删除了我们的所有图像 /var/uploads/cache 文件夹,并重新测试。 我们在 GTmetrix 上的结果表明我们能够提高 5%:

仍有改进的空间,但在 99% 的情况下,我们为改进图像所采取的步骤就足够了。

我们还去了 Pingdom Tools 检查我们的网站——我们惊讶地发现我们得到了 100% 的分数。 尽管页面加载时间仍然不尽如人意,但这比我们之前获得的 92% 分数有了显着改善:

这些建议是一个有用的指南,但如果我们的加载时间保持在 4.21 秒,我们的 100% 分数将只是一个虚荣指标,所以我们打开了 Nginx 缓存,我们在使用 Nginx 和 pm-static 进行服务器端优化中写过。 启用缓存后,我们的结果现在在所有指标上都是 100%,并且我们的加载时间低于 1 秒:

我们附上了这个测试的 HAR 文件。

结论

尽管我们使用 Pingdom 工具获得了 100 分中的 100 分,但在 YSlow 和 PageSpeed (GTmetrix) 上仍有一些指标并非 100% 令人满意。 然而,这些事情是我们无法控制的——比如其他 CDN 服务的资源(jQuery 和 Bootstrap)的缩小。 我们可以下载并缩小它们,但由于资源的广泛采用,考虑到大多数人已经在浏览器中下载了它们,这会有多大用处值得怀疑。

有些东西我们在本文中没有涉及,但在生产中会被推荐——或者至少值得探索——比如 Brotli 压缩。 Cloudflare 的人们写了一篇有趣的博客文章,介绍他们使用这种压缩算法的结果。 与所有其他事情一样,在实际实施之前,有必要对不同种类的资源和访问者连接进行彻底测试。 我们认为,在启用 HTTP 缓存的情况下,即使是高压缩比可能产生的 CPU 压缩成本仍然会得到回报,因为这是一次性成本。

Nginx 的 Brotli 压缩模块可以在这里找到。 本文将进一步探讨该主题。

如果您知道任何其他可能显着影响性能的改进,请告诉我们!

阅读更多

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注