网页性能: 缓存效率实践

[]()php

Ryan Albrecht
caisijie 翻译于2015/12/21android

任何网站都会考虑性能,不论是当地的理发店或者有巨大知识库的维基百科。这是一个没法被忽略的需求。所以缓存变得尤为重要 —— 一种让网站变快的极佳途径,经过保存部分数据,使得下次访问时不用再次计算或者下载。web

咱们团队最近在讨论Facebook.com没有被缓存的的部分网页,问题就来了:Facebook每两天发布一次代码,缓存的效率有多高?咱们是否发布代码太频繁致使浏览器的缓存没有充分利用?为了找到答案,咱们在Yahoo's Performance Research blog 发现一篇研究关于浏览器缓存对网页性能的影响的文章。数据库

咱们从中惊讶的发现一个悲观的结论:有20%的页面访问没有通过缓存。可是这份研究至今已超过8年,那时候浏览器还没法显示如顶部截图那样的瀑布式流量图,那时候IE7和jQuery才发布了几个月。我想忘记这份研究吧,jQuery 1.0 —— 老掉牙了。为了获得更精确的结果,咱们决定从新测试看看事情是否有所改观。浏览器

重开课题

在原来的研究中,Yahoo构造的一种带特殊头的图片。这些头会告诉浏览器若是一样的图片被请求两次,不会进行正常的请求,而是根据图片是否变更这个条件发送GET请求。这种GET请求会把最后修改时间的头传给服务器,若是请求时间和图片最后修改时间间隔过小,则返回304没有修改而是否是200成功。Yahoo最后查看服务器日志进行分析。缓存

与之相似,咱们构建了一个PHP终端来提供图片以及向数据库记录请求。图片附带特殊的头来控制浏览器的缓存和中间件的缓存,并且咱们会在请求同时记录全部头的信息。而响应头以下:服务器

Cache-Control: no-cache, private, max-age=0
ETag: abcde
Expires: Thu, 15 Apr 2014 20:00:00 GMT
Pragma: private
Last-Modified: $now // RFC1123 format

在IE7和IE8下,为了绕过一些已知问题,须要特殊修改:post

Cache-Control: private, max-age=0
Pragma: no-cache

当浏览器请求图片时,会没有附带或者附带一到两个额外头部:性能

  1. 没有额外头部,由于浏览器并不认识这个图片。咱们返回Status: 200 Success 以及 image data ,而后浏览器会缓存这些内容。并生成Last-Modified 时间和 ETag值会已备下次使用。测试

  2. if-none-match 和 if-modified-since 头的一个或两个,它说明浏览器以前获取过图片。服务器会返回Status: 304 Not Modified而且不包含图片数据。咱们还把Last-Modified头设置为$header['if-modified-since']而不是$now,这样浏览器每次就能得到相同的响应内容。

最后的问题就是何时和在哪里发送图片请求。咱们决定在Facebook搜索条旁边包含一个img标签,这样Facebook每次重载的时候就会渲染。在一个整个页面的重载中,内存资源会被卸载,而后浏览器根据缓存头从新请求CSS,JavaScript和咱们的图片。因此这是测量缓存是否工做的最佳位置。

在准备好终端去记录请求日志和让img标签去发送请求以后,咱们立刻开始...

研究结果

通过几周的数据收集和填满缓存,对比最后超过7天的数据。初次结果一样出乎意料:25.5%的请求没有命中缓存。咱们把数据按接口分类,桌面和移动设备,可是结果类似:桌面版24.8%以及移动版的26.9%请求没有命中缓存。这不是指望的结果,因此咱们继续深刻调试。

把桌面数据按浏览器划分后变得一目了然。

上图显示了桌面浏览器一周内的缓存命中率。使用Chrome和Opera显然从浏览器缓存受益更多。你可能注意到Fireforx并无出如今表中,这是有缘由的。Firefox v31和早期版本用当前方法测试的缓存命中率为80%,过v32版本及以上却大大的降低。v32 版本说明解释了缓存后台会 记录并重用最近的响应头。若是重用响应,咱们的终端就无法收到请求并记录日志。这样测试会错误的认为Firefox表现糟糕。但实际上仍在命中本地缓存;只是没法统计信息。考虑到这点,咱们把Firefox排除在测试结果以外。

让咱们看看移动端的状况

不一样产品的缓存命中在68%和84%之间浮动,和以前的线差很少。移动端的变更性更多,由于许多不一样  year class 的设备在访问移动网页,并且每个浏览器版本都有一个可能的范围。这些数字广泛比桌面版的低可是排序基本一致。

咱们还能够看看不一样用户命中空缓存的比例

平均44.6%的用户获取了空缓存。这佐证了Yahoo在2007年关于每一个用户命中率的结果。

更进一步

尚未完呢。在Facebook,咱们但愿小步快走的天天两次地发布包含当天完成的全部优秀功能。这就引出一个问题:浏览器缓存生命周期是多少?咱们能够经过把请求头if-modified-since的值减去当前时间值,这样就能够获得这个用户命中缓存的存活时间。

因此咱们发掘数据。仍然是最近一周的数据,咱们生成描述缓存持续命中(请求返回304)时间分布的柱状图。换一种说法,每次从新获取图片的间隔有多长。

横轴 duration 单位是小时,竖线 p50_(百分之50), _mean_(平均)和 _p75(百分之75)分别表示对应请求比例的缓存时间。好比,_p50 表示50%的请求在命中最多47小时以前生成的缓存,相似的 p75 代表25%的请求的缓存存在的时间至少有260个小时。在移动端作一样的分析显示有50%的请求的缓存不会超过12个小时。

实际应用

总的来看缓存命中率相比2007年有所提升。若是忽略Firefox v32及以上版本(没法测试),这样缓存命中率由2007年的80%左右提升到如今的84.1%。另外一方面,缓存保持活跃的时间并非很长。根据咱们的研究,在桌面版,有42%几率任何请求的缓存的存在时间不超过47小时。这是一个新的维度,并且在某些网站影响突出。

很容易解释为何缓存存在时间一般很短。看看因特网如何传输和网页大小size从2007年至今的变化。在2007年,家庭有线带宽是2.5Mbps,Yahoo主页168.1KB。现在,我有8Mbps的LTE移动下载带宽,Yahoo主页是768KB。如今网页平均大小是1MB,对浏览器优化形成了更大的压力。

所以利用好浏览器缓存仍然重要,若是用好带来的收益也会比8年前更大。咱们的最佳实践是使用外部样式和脚本,包含Cache-Control和Etag头,传输层数据压缩,使用URL使缓存资源失效,把平凡更新的资源和稳定资源分开。全部这些技术都能在任何网站协同工做,而不仅仅是Facebook。咱们一开始担忧本身的发布流程会给缓存性能带来负面影响,但结果并非这样。实际上,咱们使用这份数据专一于改进让全部人访问www.facebook.com都能经过缓存。真是有意思的一次缓存挖掘之旅。

相关文章
相关标签/搜索