180

问题 A 部分▉(100 赏金,奖励)
主要问题是如何让这个网站加载更快。首先,我们需要阅读这些瀑布。感谢大家对瀑布读数分析的建议。从这里显示的各种瀑布图中可以看出主要瓶颈:PHP 生成的缩略图。David 建议的从 CDN 加载的无协议 jquery 得到了我的赏金,尽管它使我的网站整体速度只提高了 3%,而且没有解决网站的主要瓶颈。是时候澄清我的问题了,还有另一个赏金:

Question Part B ▉ (100 bountys, 已获奖)
现在的新重点是解决 6 jpg 图像所存在的问题,这是导致大部分加载延迟的问题。这 6 张图片是 PHP 生成的缩略图,很小,只有 3~5 kb,但加载速度相对较慢。注意各种图表上的“第一个字节的时间”。问题仍未解决,但詹姆斯得到了赏金,他修复了 RedBot下划线的标题错误:“一个 If-Modified-Since 条件请求返回了完整的内容不变。” .

问题 C 部分▉(我的最后一次赏金:250 分)
不幸的是,在修复了 REdbot.org 标头错误之后,PHP 生成的图像造成的延迟仍然没有改变。这些微小的 3~5Kb 缩略图到底在想什么?所有这些标题信息都可以将火箭发送到月球并返回。非常感谢有关此瓶颈的任何建议并将其视为可能的答案,因为我已经被这个瓶颈问题困扰了七个月了。

[我网站上的一些背景信息:CSS 位于顶部。底部的 JS(Jquery、JQuery UI、购买的菜单 awm/menu.js 引擎、tabs js 引擎、视频 swfobject.js) 第二张图片上的黑线显示了启动加载的内容。愤怒的机器人是我的宠物“ZAM”。他是无害的,而且常常更快乐。]


负载瀑布:按时间顺序| http://webpagetest.org 在此处输入图像描述


并行域分组| http://webpagetest.org 在此处输入图像描述


Site-Perf 瀑布| http://site-perf.com 在此处输入图像描述


Pingdom 工具瀑布 | http://tools.pingdom.com

在此处输入图像描述


GTmetrix 瀑布 | http://gtmetrix.com

在此处输入图像描述


4

19 回答 19

61

首先,使用这些多个域需要多次 DNS 查找。您最好将其中许多图像组合成一个精灵,而不是分散请求。

其次,当我加载您的页面时,我在 all.js 上看到了大部分阻塞(约 1.25 秒)。我看到它以(旧版本的)jQuery 开头。您应该从 Google CDN 引用它,不仅可以减少加载时间,还可以完全避免对它的 HTTP 请求。

具体来说,可以在这些 URL 上引用最新的 jQuery 和 jQuery UI 库(如果您对我省略 的原因感兴趣,请参阅这篇文章http:):

//ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js

//ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js

如果您使用默认的 jQuery UI 主题之一,您还可以从 Google CDN 中提取其 CSS 和图像

优化 jQuery 托管后,您还应该将其合并awmlib2.jstooltiplib.js一个文件中。

如果您解决了这些问题,您应该会看到显着的改进。

于 2011-01-27T09:12:39.570 回答
17

几天前我遇到了类似的问题,我发现了 head.js。这是一个 Javascript 插件,允许您并行加载所有 JS 文件。希望有帮助。

于 2011-01-30T21:44:58.697 回答
12

我远非专家,但...

关于这一点:“一个 If-Modified-Since 条件请求返回完整内容不变。” 和我的评论。

用于生成缩略图的代码应检查以下内容:

  1. 是否有缩略图的缓存版本。
  2. 缓存版本是否比原始图像新。

如果其中任何一个为假,则无论如何都应生成并返回缩略图。如果它们都为真,则应进行以下检查:

  1. 是否有 HTTP_IF_MODIFIED_SINCE 标头
  2. 缓存版本的最后修改时间是否与 HTTP_IF_MODIFIED_SINCE 相同

如果其中任何一个为假,则应返回缓存的缩略图。

如果这两个都为真,则应返回 304 http 状态。我不确定它是否需要,但我也亲自返回 Cache-Control、Expires 和 Last-Modified 标头以及 304。

关于 GZipping,我被告知不需要 GZip 图像,因此请忽略我评论的那部分。

编辑:我没有注意到您对帖子的添加。

session_cache_limiter('public');
header("Content-type: " . $this->_mime);
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 2419200) . " GMT");
// I'm sure Last-Modified should be a static value. not dynamic as you have it here.
header("Last-Modified: " . gmdate("D, d M Y H:i:s",time() - 404800000) . " GMT");

我还确定您的代码需要检查 HTTP_IF_MODIFIED_SINCE 标头并对其做出反应。仅设置这些标头和您的 .htaccess 文件不会提供所需的结果。

我认为你需要这样的东西:

$date = 'D, d M Y H:i:s T'; // DATE_RFC850
$modified = filemtime($filename);
$expires = strtotime('1 year'); // 1 Year

header(sprintf('Cache-Control: %s, max-age=%s', 'public', $expires - time()));
header(sprintf('Expires: %s', date($date, $expires)));
header(sprintf('Last-Modified: %s', date($date, $modified)));
header(sprintf('Content-Type: %s', $mime));

if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
    if(strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) === $modified) {
        header('HTTP/1.1 304 Not Modified', true, 304);
        // Should have been an exit not a return. After sending the not modified http
        // code, the script should end and return no content.
        exit();
    }
}
// Render image data
于 2011-02-09T13:40:05.337 回答
6

哇,很难用这张图片来解释事情。但是在这里,一些尝试:

  • 文件 33-36 加载较晚,因为它们是在 swf 中动态加载的,并且 swf (25) 在加载任何其他内容之前首先完全加载
  • 文件 20 和 21可能是(我不知道,因为我不知道您的代码)由 all.js(11)加载的库,但要执行 11,它会等待整个页面(和资产)加载(您应该将其更改为 domready)
  • 文件 22-32 由这两个库加载,在完全加载之后再次加载
于 2011-01-26T22:39:03.807 回答
4

只是一个简单的猜测,因为这种分析需要大量的 A/B 测试:您的 .ch 域似乎很难到达(第一个字节到达之前的长长的绿色条带)。

这意味着 .ch 网站的托管状况不佳,或者您的 ISP 没有通往它们的良好路径。

鉴于图表,这可以解释巨大的性能损失。

附带说明一下,有一个很酷的工具cuzillion可以帮助您根据资源加载的顺序来解决问题。

于 2011-01-26T22:41:36.070 回答
4

如果没有很好的理由(通常没有),您的图像不应调用 PHP 解释器。

为您的 Web 服务器创建一个重写规则,如果在文件系统上找到该图像,则直接为该图像提供服务。如果不是,请重定向到您的 PHP 脚本以生成图像。编辑图像时,更改图像文件名以强制具有缓存版本的用户获取新编辑的图像。

如果它至少不起作用,那么现在它与创建和检查图像的方式没有任何关系。

于 2011-02-24T21:27:00.607 回答
4

我找到了您网站的 URL,并从主页检查了一个单独的 jpg 文件。虽然现在加载时间是合理的(161 毫秒),但它等待 126 毫秒,这太过分了。

您最后修改的标题都设置为 2011 年 1 月 1 日星期六 12:00:00 GMT,这看起来太“圆”而不是真正的生成日期 ;-)

由于 Cache-control 是“public, max-age=14515200”,任意最后修改的标头可能会在 168 天后导致问题。

无论如何,这不是延误的真正原因。

当缩略图已经存在时,您必须检查您的缩略图生成器会做什么,以及检查和交付图片可能会消耗这么多时间。

您可以安装xdebug来分析脚本并查看瓶颈在哪里。

也许整个事情都使用了一个框架或连接到某个数据库。我在某些服务器上看到 mysql_connect() 非常慢,主要是因为它们使用 TCP 而不是套接字进行连接,有时会出现一些 DNS 问题。

我知道您不能在这里发布您的付费发电机,但恐怕有太多可能的问题......

于 2011-02-23T23:14:21.153 回答
4

尝试在您的站点/页面上运行 Y!Slow 和 Page Speed 测试,并按照指南排除可能的性能瓶颈。一旦您在 Y!Slow 或 Page Speed 中得分较高,您应该会获得巨大的性能提升。

这些测试将告诉您哪里出了问题以及需要改变什么。

于 2011-01-27T08:55:05.923 回答
4

所以你的 PHP 脚本在每次页面加载时都会生成缩略图?首先,如果缩略图的图像不经常更改,您是否可以设置一个缓存,以便在每次页面加载时都不必解析它们?其次,您的 PHP 脚本是否使用类似imagecopyresampled()创建缩略图的方法?这是一个不平凡的下采样,PHP 脚本在缩小内容之前不会返回任何内容。改为使用imagecopymerged()会降低图像质量,但会加快处理速度。你做了多少减少?这些缩略图是原始图像大小的 5% 还是 50%?原始图像的较大尺寸可能会导致速度变慢,因为 PHP 脚本必须先将原始图像保存在内存中,然后才能缩小它并输出较小的缩略图。

于 2011-02-07T20:31:04.687 回答
3

调查 PHP 对会话数据的使用。也许(只是也许),生成图像的 PHP 脚本正在等待锁定会话数据,该会话数据被仍在渲染的主页或其他图像渲染脚本锁定。这将使所有 JavaScript/浏览器优化几乎无关紧要,因为浏览器正在等待服务器。

PHP 为每个正在运行的脚本锁定会话数据,从会话处理开始的那一刻到脚本完成的那一刻,或者当 session_write_close() 被调用时。这有效地序列化了事物。查看有关会话的 PHP 页面,尤其是评论,例如这个

于 2011-02-11T23:31:16.213 回答
3

这只是一个疯狂的猜测,因为我没有查看您的代码,但我怀疑会话可能在这里发挥作用,以下来自 PHP 手册条目session_write_close()

会话数据通常在脚本终止后存储,无需调用 session_write_close(),但由于会话数据被锁定以防止并发写入,任何时候只有一个脚本可以对会话进行操作。将框架集与会话一起使用时,由于这种锁定,您将体验到一个一个加载的框架。您可以通过在会话变量的所有更改完成后立即结束会话来减少加载所有帧所需的时间。

就像我说的,我不知道你的代码在做什么,但这些图表看起来很可疑。我在编写多部分文件服务功能时遇到了类似的问题,并且遇到了同样的问题。提供大文件时,我无法使用多部分功能,也无法打开另一个页面,直到下载完成。打电话session_write_close()解决了我的两个问题。

于 2011-03-04T21:38:37.147 回答
2

我认为,与其使用缩略图生成器脚本,不如尝试一下TinySRC以快速生成云托管的缩略图。它有一个非常简单易用的 API,你可以像这样使用:-

http://i.tinysrc.mobi/ [高度] / [宽度] /http://domain.tld/path_to_img.jpg

[宽度](可选):- 这是以像素为单位的宽度(覆盖自适应或系列大小)。如果以“-”或“x”为前缀,它将减去或缩小到确定大小的百分比。

[高度](可选):- 如果宽度也存在,这是以像素为单位的高度。它还覆盖自适应或系列大小,并且可以以“-”或“x”为前缀。

您可以在此处查看 API 摘要


常问问题

tinySrc 花了我多少钱?

没有什么。

我什么时候可以开始使用 tinySrc?

现在。

服务的可靠性如何?

我们对 tinySrc 服务不做任何保证。但是,它在主要的分布式云基础架构上运行,因此它在全球范围内提供高可用性。它应该足以满足您的所有需求。

它有多快?

tinySrc 在内存和我们的数据存储中缓存调整大小的图像长达 24 小时,并且它不会每次都获取您的原始图像。从用户的角度来看,这使得服务速度非常快。(并减少您的服务器负载作为一个很好的副作用。)


祝你好运。只是一个建议,因为你没有向我们展示代码:p

于 2011-03-04T20:43:28.567 回答
2

您是否尝试过用常规图像替换 php 生成的缩略图以查看是否有任何区别?问题可能出在 - 导致每次服务器调用时重新生成缩略图的 php 代码中的错误 - 与时钟问题相关的代码延迟(sleep()?) - 导致非常糟糕的竞争条件的硬盘问题因为所有缩略图都是同时加载/生成的。

于 2011-02-25T02:13:39.150 回答
2

由于某些浏览器每个域只下载 2 个并行下载,您是否可以不添加额外的域来将请求分片到两到三个不同的主机名上。例如 1.imagecdn.com 2.imagecdn.com

于 2011-03-11T16:32:51.700 回答
1

关于延迟缩略图,请尝试在缩略图生成脚本中最后一次调用header()之后立即调用flush() 。完成后,重新生成您的瀑布图并查看延迟现在是否在正文而不是标题上。如果是这样,您需要仔细查看生成和/或输出图像数据的逻辑。

希望处理缩略图的脚本应该使用某种缓存,以便它对您所提供的图像采取的任何操作都只会在绝对必要时发生。每次您提供缩略图时,似乎都会发生一些昂贵的操作,这会延迟脚本的任何输出(包括标题)。

于 2011-02-28T19:11:23.110 回答
1

大多数缓慢的问题是您的 TTFB(到第一个字节的时间)太高。如果不深入了解您的服务器配置文件、代码和底层硬件,这是一个很难解决的问题,但我可以看到它在每个请求中都很猖獗。你有太多的绿色条(坏)和很少的蓝色条(好)。您可能想停止对前端进行一点优化,因为我相信您在该领域已经做了很多工作。尽管“ 80%-90% 的最终用户响应时间都花在了前端”这句格言,但我相信你的反应发生在后端。

TTFB是后端的东西,服务器的东西,输出和握手之前的预处理。

为您的代码执行计时以查找慢速数据库查询等慢速内容、输入和退出函数/方法以查找慢速函数的时间。如果您使用 php,请尝试Firephp。有时它是在启动或初始化期间运行一两个慢查询,例如提取会话信息或检查身份验证等等。优化查询可以带来一些好的性能增益。有时代码使用 php prepend 或 spl autoload 运行,因此它们可以在所有内容上运行。其他时候,它可能是错误配置的 apache conf 和调整以节省时间。

寻找低效的循环。查找因磁盘驱动器故障或磁盘空间使用率高而导致的缓存调用缓慢或 i/o 操作缓慢。查找内存使用情况以及正在使用的内容和位置。仅使用来自世界各地不同位置而不是同一位置的第一个视图,对单个图像或文件运行 10 次运行的网页测试重复测试。并阅读您的访问和错误日​​志,太多的开发人员会忽略它们,只依赖于输出的屏幕错误。如果您的虚拟主机有支持,请向他们寻求帮助,如果他们不礼貌地向他们寻求帮助,那也不会受到伤害。

您可以尝试 DNS Prefetching 来对抗许多域和资源,http://html5boilerplate.com/docs/DNS-Prefetching/

您自己的服务器是好/体面的服务器吗?有时更好的服务器可以解决很多问题。我是“硬件便宜,程序员贵”心态的粉丝,如果你有机会和金钱升级服务器。和/或使用像maxcdncloudflare或类似的 CDN。

祝你好运!

(ps 我不为这些公司工作。另外,上面的 cloudflare 链接会认为 TTFB 并不那么重要,我把它扔在那里,这样你就可以再拿一次了。)

于 2012-07-24T01:34:56.683 回答
1

首先If-Modified-Since,正如詹姆斯所说,您需要适当地处理请求等。该错误指出:“当我询问您的服务器自上次以来该图像是否被修改时,它会发送整个图像而不是简单的是/否”。

连接和第一个字节之间的时间通常是您的 PHP 脚本运行所需的时间。很明显,当该脚本开始运行时正在发生某些事情。

  1. 您是否考虑过对其进行剖析?它可能有一些问题。
  2. 结合上述问题,您的脚本可能运行的次数可能比需要的多得多。理想情况下,它应该在原始图像被修改并为每个其他请求发送缓存的缩略图时才生成缩略图。您是否检查过脚本是否不必要地生成图像(例如,对于每个请求)?

通过应用程序生成正确的标头有点棘手,而且它们可能会被服务器覆盖。而且您会受到滥用,因为任何发送一些无缓存请求标头的人都会导致您的缩略图生成器连续运行(并增加负载)。因此,如果可能,请尝试保存这些生成的缩略图,直接从您的页面调用保存的图像并从.htaccess. .htaccess在这种情况下,如果您的服务器配置正确,您甚至不需要任何东西。

除此之外,您可以从这个整体不错的 SO 问题的性能部分应用一些关于如何以正确的方式做网站的出色优化想法,例如将您的资源拆分为无 cookie 的子域等。但无论如何,一张 3k 图像不应该花一秒钟的时间来加载,与图中的其他项目相比,这一点很明显。您应该在优化之前尝试发现问题。

于 2011-02-10T09:49:01.590 回答
1

您是否尝试过在NGINX 网络服务器下设置几个子域专门用于提供静态数据,如图像和样式表?在这个主题中可能已经找到了一些有用的东西。

于 2011-02-22T00:49:05.597 回答
-1

很抱歉,您提供的数据很少。你已经提出了一些很好的建议。

您如何提供这些图像?如果您通过 PHP 流式传输这些内容,那么您正在做一件非常糟糕的事情,即使它们已经生成。

永远不要使用 PHP 流式传输图像。无论您以何种方式使用它,它都会减慢您的服务器速度。

将它们放在一个可访问的文件夹中,并带有一个有意义的 URI。然后直接使用它们的真实 URI 调用它们。如果您需要即时生成,您应该在图像目录中放置一个 .htaccess,仅当请求图像丢失时才会重定向到生成器 php-script。(这称为缓存请求策略)。

这样做将同时修复 php 会话、浏览器代理、缓存、ETAGS 等等。

如果配置正确,WP-Supercache 使用此策略。

我前段时间写了这篇文章(http://code.google.com/p/cache-on-request/source/detail?r=8),最后的修订版被破坏了,但我想 8 或更少应该可以工作,你可以拿 .htaccess 作为一个例子,只是为了测试一下(尽管有比我以前更好的方法来配置 .htaccess)。

我在这篇博文 ( http://www.stefanoforenza.com/need-for-cache/ ) 中描述了该策略。它可能写得不好,但它可能有助于澄清事情。

进一步阅读: http: //meta.wikimedia.org/wiki/404_handler_caching

于 2011-03-06T17:21:22.447 回答