caching,PHP生成缩略图加载缓慢

问题A部分 ▉(100奖励,颁发)
主要问题是如何使这个网站,加载速度更快。 首先,我们需要阅读这些瀑布。 感谢所有关于瀑布读数分析的build议。 从这里显示的各种瀑布图显示的主要瓶颈是:PHP生成的缩略图。 从大卫build议的CDN的无协议jquery加载得到我的赏金,虽然使我的网站整体速度只有3%,而没有回答该网站的主要瓶颈。 是时候澄清我的问题了,另一个赏金:

问题B部分 ▉(100奖励,颁发)
现在新的重点是解决6 jpg图像的问题,这是造成大部分加载延迟的问题。 这6张图片是PHP生成的缩略图,很小,只有3〜5kb,但是加载速度相对慢。 注意各个图表上的“ 第一个字节的时间 ”。 问题仍然没有得到解决,但一个赏金去了詹姆斯,他修复了RedBot 强调的头错误: “如果修改,因为有条件的请求返回完整的内容不变。

问题C部分 ▉(我最后的赏金:250分)
不幸的是,甚至在修复了REdbot.org头部错误之后,由PHP生成的图像所引起的延迟仍未改变。 这些小小的3〜5Kb缩略图究竟在想些什么? 所有的头文件信息可以发送火箭到月球和背部。 任何关于这个瓶颈的build议都是值得赞赏的,并被视为可能的答案,因为我已经在这个七个月的瓶颈问题上陷入了困境。 我提前感谢。

[我的网站上的一些背景信息:CSS位于顶部。 JS的底部(JQuery的,JQuery的UI,购买了菜单awm / menu.js引擎,标签JS引擎,videoswfobject.js)第二个图像上的黑线显示什么是什么启动加载。 愤怒的机器人是我的宠物“ZAM”。 他是无害的,往往更快乐。]


加载瀑布:按时间顺序 | http://webpagetest.org 在这里输入图像说明


并行域分组 | http://webpagetest.org 在这里输入图像说明


Site-Perf瀑布 | http://site-perf.com 在这里输入图像说明


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

在这里输入图像说明


GTmetrix瀑布 | http://gtmetrix.com

在这里输入图像说明


首先,使用这些多个域需要几个DNS查找。 你最好将许多这些图像组合成精灵而不是传播请求。

其次,当我加载你的页面时,我看到all.js的大部分阻塞(〜1.25s)。 我看到,从(旧版本的)jQuery开始。 您应该从Google CDN中引用它,不仅可以减less加载时间 ,还可以完全避免HTTP请求 。

具体来说,最新的jQuery和jQuery用户界面库可以在这些url被引用(如果你感兴趣的话,请参阅这篇文章 ,为什么我省略了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主题之一,您还可以将其CSS和图像从Google CDN中提取出来 。

在优化jQuery托pipe的同时,您还应该将awmlib2.jstooltiplib.js合并到一个文件中。

如果你解决这些问题,你应该看到一个重大的进步。

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

我远离专家,但…

关于这一点:“如果修改 – 由于条件请求返回完整的内容不变。 和我的意见。

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

  1. 有没有一个caching版本的缩略图。
  2. caching版本比原始图像更新。

如果其中任何一个都是错误的,则无论如何都应该生成并返回缩略图。 如果他们都是真的,那么应该做下面的检查:

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

如果其中任何一个都是错误的,则应该返回caching的缩略图。

如果这两个都是真的,那么应该返回304的http状态。 我不确定是否需要它,但我也亲自返回caching控制,过期和最后修改头随着304。

关于GZipping,我已经被告知,没有必要GZip图像,所以忽略我的评论的一部分。

编辑:我没有注意到你的post的增加。

 session_cache_limiter('public'); header("Content-type: " . $this->_mime); header("Expires: " . gmdate("D, d MYH: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 MYH:i:s",time() - 404800000) . " GMT"); 

我也确信你的代码需要检查HTTP_IF_MODIFIED_SINCE头并对其做出反应。 只是设置这些头文件和你的.htaccess文件将不会提供所需的结果。

我想你需要这样的东西:

 $date = 'D, d MYH: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 

哇,很难用这个图像来解释事情。但是在这里,有些人试图:

  • 文件33-36的加载迟了,因为它们在swf中被dynamic地加载,并且swf(25)在它加载任何附加内容之前被完全加载
  • 文件20和21 可能 (我不知道,因为我不知道你的代码)由all.js(11)加载,但为了执行11,它等待整个页面(和资产)加载(你应该改变它domready)
  • 这些文件22-32由这两个库加载,然后在完全加载之后再次加载

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

这意味着.ch网站的托pipe不好,或者你的ISP没有一个好的路线。

鉴于这些图表,这可以解释一个重大的性能问题。

在一个侧面说明,这是一个很酷的工具cuzillion ,可以帮助您根据您的资源加载顺序进行分类。

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

这些testing会告诉你什么是错的,以及要改变什么。

所以你的PHP脚本在每个页面加载时都会生成缩略图? 首先,如果正在缩略图的图像没有经常更改,您可以设置一个caching,以便每次页面加载时不必进行分析。 其次,你的PHP脚本是否使用类似imagecopyresampled()来创build缩略图? 这是一个不小的缩减范例,PHP脚本不会返回任何东西,直到完成缩小的事情。 使用imagecopymerged()会降低图像的质量,但会加快处理速度。 你在做多less减less? 这些缩略图是原始图像大小的5%还是50%? 由于PHP脚本必须在内存中获取原始图像,才能缩小原始图像并输出较小的缩略图,原始图像的尺寸可能会变大。

我find了您网站的url,并从主页上检查了一个单独的jpg文件。 现在装载时间合理(161毫秒),等待126毫秒,这是太多了。

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

由于Cache-control是“public,max-age = 14515200”,任意的最后修改的标题将会在168天之后引起问题。

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

您必须检查缩略图生成器在缩略图已经存在时所做的操作,以及可能会花费太多时间来检查和传送图片。

你可以安装xdebug来分析脚本,看看瓶颈在哪里。

也许整个事情使用一个框架或连接到一些数据库没有任何东西。 我在某些服务器上看到了非常慢的mysql_connect(),主要是因为它们使用TCP而不是socket连接,有时会遇到一些DNS问题。

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

如果没有一个很好的理由(通常没有),你的图片不应该调用PHP解释器。

如果在文件系统上find,则直接为图像服务器创build一个重写规则。 如果不是,redirect到您的PHP脚本生成图像。 编辑图像时,更改图像文件名以强制具有caching版本的用户获取新编辑的图像。

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

调查PHP的会话数据的使用情况。 也许(也许),图像生成PHP脚本正在等待会话数据的locking,会话数据被仍然呈现的主页面或其他图像呈现脚本locking。 这将使所有的JavaScript /浏览器优化几乎不相关,因为浏览器正在等待服务器。

PHP会locking从会话处理开始的那一刻起到脚本结束的时刻或调用session_write_close()的每个脚本的会话数据。 这有效地序列化的东西。 查看会话中的PHP页面,特别是注释,就像这个一样。

这只是一个疯狂的猜测,因为我没有看过你的代码,但我怀疑会话可能在这里扮演一个angular色,以下是来自session_write_close()上的PHP手册条目:

会话数据通常是在脚本终止后存储的,不需要调用session_write_close(),但是由于会话数据被locking以防止并发写入,所以任何时候只有一个脚本可以在会话上运行。 将帧集与会话一起使用时,由于此locking,您将体验逐帧加载的帧。 只要完成对会话variables的所有更改,就可以通过结束会话来缩短加载所有帧所需的时间。

就像我说的,我不知道你的代码在做什么,但是这些图似乎很奇怪。 当我编码一个多部分文件服务function ,我也有类似的问题,我有同样的问题。 在提供大文件时,无法使多部分function正常工作,也不能在下载完成之前打开另一个页面。 调用session_write_close()解决了我的问题。

你有没有试过用常规图像replacephp生成的thumnails来查看是否有任何区别? 问题可能在于 – PHP代码中的一个错误导致在每个服务器调用时重新生成缩略图 – 与时钟问题相关的代码中的延迟(sleep()?) – 导致非常差的竞争条件的硬驱问题因为所有的缩略图都是同时加载/生成的。

我认为,不要使用缩略图生成器脚本 ,而必须让TinySRC尝试快速,云托pipe的缩略图生成。 它有一个非常简单和易于使用的API,你可以使用像: –

http://i.tinysrc.mobi/ [height] / [width] /http://domain.tld/path_to_img.jpg

[宽度] (可选): – 这是以像素为单位的宽度(这会覆盖自适应或家庭大小)。 如果以“ – ”或“x”作为前缀,则将从所确定的大小中减去或缩小到一定百分比。

[高度] (可选): – 如果宽度也存在,则以像素为单位。 它也覆盖适应性或家庭大小,并且可以以“ – ”或“x”作为前缀。

您可以在这里查看API摘要


常问问题

tinySrc花了我多less钱?

没有。

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

现在。

这项服务有多可靠?

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

它有多快?

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


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

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

首先,你需要像James说的那样适当地处理If-Modified-Since请求。 该错误指出:“当我问你的服务器,如果该图像自上次以来被修改,它发送整个图像,而不是简单的是/否”。

连接和第一个字节之间的时间通常是PHP脚本运行的时间。 当脚本开始运行时,显然发生了一些事情。

  1. 你考虑过分析吗? 它可能有一些问题。
  2. 结合上述问题,您的脚本可能会运行比需要更多的时间。 理想情况下, 只有在原始图像被修改的情况下,才会产生大拇指,并为每个其他请求发送caching的大拇指。 你有没有检查脚本是不必要地生成图像(例如,每个请求)?

通过应用程序生成正确的标题有点棘手,再加上它们可能会被服务器覆盖。 而且你暴露在滥用,任何发送一些无caching请求标头的人都会导致你的缩略图生成器连续运行(并提高负载)。 因此,如果可能,请尝试保存生成的大拇指,直接从页面调用保存的图像,并pipe理.htaccess标题。 在这种情况下,如果你的服务器configuration正确,你甚至不需要你的.htaccess任何东西。

除此之外,你可以应用一些明智的优化思路,从这个总体上好的问题的性能部分, 如何做正确的方式做网站 ,如分裂你的资源到无cookie的子域,等等。但无论如何,一个3K图像不应该花一秒钟加载,与图表中的其他项目相比,这是显而易见的。 您应该尝试在优化之前发现问题。

你有没有试过在NGINX网站服务器下设置好几个子域,专门用来提供图片和样式表等静态数据? 在这个主题中可以find有用的东西。

关于延迟缩略图,尝试在缩略图生成脚本中最后一次调用header()之后立即调用flush() 。 一旦完成,重新生成你的瀑布图,看看是否延迟现在在身体而不是标题。 如果是这样的话,您需要长时间观察生成和/或输出图像数据的逻辑。

处理缩略图的脚本应该有希望使用某种caching,以便在所有服务上执行的操作只会在绝对必要时才会发生。 看起来像是一些昂贵的操作正在发生,每当你提供延迟的任何输出(包括标题)从脚本缩略图。

大部分缓慢的问题是您的TTFB(第一个字节的时间)太高。 如果没有与服务器configuration文件,代码和底层硬件密切相关,这是一个难以解决的问题,但是我可以看到它在每个请求中都很猖獗。 你有太多的绿色酒吧(坏)和很less的蓝色酒吧(好)。 你可能想停止优化前端,因为我相信你在这方面做了很多。 尽pipe“ 最终用户响应时间的80%-90%花在了前端 ”这句格言,我相信你是在后端发生的。

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

定时执行代码以查找缓慢的数据库查询,进入和退出函数/方法以查找慢速函数等缓慢的内容。 如果您使用PHP,请尝试Firephp 。 有时候,在启动或初始化过程中会运行一两个缓慢的查询,例如拉取会话信息或检查身份validation,还有哪些不是。 优化查询可以带来一些很好的性能提升。 有时候,代码是使用php prepend或者spl自动加载来运行的,所以它们可以运行在任何东西上 其他时候,它可以是错误的configurationapache conf和调整,节省一天。

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

您可以尝试DNS预取以对付多个域和资源, http://html5boilerplate.com/docs/DNS-Prefetching/

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

祝你好运!

(ps我不为这些公司工作,上面的cloudflare链接也会说TTFB不是那么重要,我把它扔在那里,所以你可以再拿一次。)

很抱歉地说,你提供了很less的数据。 而且你已经有了一些很好的build议。

你如何提供这些图像? 如果你是通过PHP来stream式传输,那么即使它们已经被生成,也是非常糟糕的。

不要用PHPstream式传输图像。 无论您使用的方式如何,它都会降低服务器速度。

把它们放在一个可访问的文件夹中,用一个有意义的URI 然后直接用它们的真实URI来调用它们。 如果你需要在飞行世代,你应该把一个.htaccess的图像目录redirect到一个生成器PHP脚本只有当请求的图像丢失。 (这被称为“请求caching”策略)。

这样做会解决PHP会话,浏览器代理,caching,ETAGS,无论一次。

WP-Supercache使用这个策略,如果configuration正确的话。

我前一段时间写了这个( http://code.google.com/p/cache-on-request/source/detail?r=8 ),最后的修改被破坏了,但是我猜应该是8或者更less,你可以以.htaccess为例,只是为了testing一下(虽然有更好的方法来configuration.htaccess比我以前的方式)。

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

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