[WebKit]管好页面缓存

“最快的网络请求就是不发请求。”


无论何时有人说到这句话,我都会心一笑。这的确是真理,HTTP Cache对网页速度至关重要。

现在缓存的使用看似正渐入佳境,但还不够。下面HTTP Archive的数据显示在过去一年里(2011),  缓存的资源增加了10%,而同时页面资源却增加了12%,页面数据量增加了24%(LINK)

推动缓存的应用涉及很多方面,无法加以明确具体的进度。唯一所能明确的是应用缓存是我们必然的选择。

下面是收集到的一些比较明显的缓存问题,可以帮助我们了解下一步要做些什么:

  • 55%的资源没有指定Max-Age
  • 没有指定Max-Age的资源中有46%的资源在2周内并没有变化过。
  • 许多常用的页面资源仅允许缓存一两个小时。
  • 40-60%的页面访问者并没有对应的缓存。
  • 30%的页面用户有页面的完整缓存可用。
  • 用户平均需要花4小时的浏览时间才能拥有页面的完整缓存。


Max-Age的分布

在以前就提到缓存的一些空间限制的问题,缺少足够HTTP请求头的Bug, 以及过期淘汰算法的问题。可是一些页面并未指定缓存的headers,比如在响应中指定Max-Age。下面的例子指定资源可以缓存一年:

   Cache-Control: max-age=31536000

你既然读了这篇博客,那你很可能已经开始运用max-age了。不过下面这分HTTP Archive的图表显示55% 的资源并未指定Max-Age,也就是平均页面资源数是81个,其中有45个资源会被反复请求。

没有使用缓存并非'有意为之'

为什么55%的资源没有指定缓存信息?很可能是页面开发者缺少使用缓存的意识,认为自己的太简单,不需要使用缓存。另一种情况是很多资源是动态的(JSON, ads, beacons, …)所以无法缓存。HTTP Archieve同样相应的统计。

HTTP Achieve会在每月的1日和15日分析世界近Top 50K个页面,并记录每个资源的HTTP headers。我们可以使用这些数据来观察缓存的变化情况。上面说到有55%无法缓存的资源是出自2012年2月15日的数据,下图则显示这些资源在近两周(2月1日)及一个月(1月15日)中的变化情况:(HTTP Archive没有保存数据体,所以这些数据的唯一性是通过相同的URL,
Last-Modified, ETag及Content-Length这些字段来标识的。)


没有指定max-age的资源中有46%超过2周没有变化过,也就是说平均每页本来可以有21个子资源是不需要的发起网络请求。另外38%的资源超过一个月没有变过,相当于平均每个页面17个这样的子资源。

可以看到这里的确有许多不必要的HTTP数据请求。个人认为这绝不是故意的,而是缺少使用缓存的意识。下面这个数据可以证明这一点,它显示出所有资源(包含所有可缓存的和不可缓存的资源)在2012年2月15日前近一年内未变化的情况。

可以看到无论是全部资源,或是未支持缓存的资源中,其中在2周及1月内未变化的比例十分相近(分别是44% vs. 46%, 及35% vs. 38%)。

*译注:下面是www.sina.com.cn的最近一年(2014/2/1)支持缓存资源的占比。:

以及缓存生命周期的分布:

对比相应的网络流量的变化情况:

可以看到缓存支持最高(81%)时,网络请求数及流量处于最低值(710kB)。

第三方内容

如果一个页面没有很好地支持缓存,只会影响他们的页面和用户。但如果一个第三方的内容开发者未能提供良好的缓存支持,就会影响到所有使用它的网页。反之,应用了较好的缓存支持,就可以大幅提升性能。

下面是HTTP Archive统计出的最常使用的30个第三方资源,以及它们的max-age值。

其中有些有趣的发现.

  • 简单的URLs有着较短的缓存时间 – 一些资源时间特别短,它们常常是在粘贴到页面中的一个片段。短的缓存时间有利于解决一些紧急的问题。
  • 较长的URLs有着同样较长的缓存时间 – 许多第三方bootstrap脚本会动态地加载其它资源,他们所生成的URLs一般都比较长,里面含有一些唯一标识符。如果出现了紧急问题,负责加载的脚本会被修改支加载不同URL的资源,这样就不需要对应更新那些资源了。
  • Facebook中点赞按钮去哪了? – Facebook的like.php和likebox.php是经常被使用的,但没有出现在上面的列表里。原因是不同的页面下会有一个唯一标识,从而降低了总体的占比。相比于那些负责加载的脚本,它们有着更为激进的过期策略,如no-cache, no-store, must-revalidate。
  • 拥有较短缓存时间的资源通常是异步的 – 为那些bootstrap脚本指定较短的缓存时间有利于应对紧急状况,但会因为发送条件更新(Conditional GET)请求而影响性能。幸运地是一些第三方资源开发者已经意识到这个问题,并提供了异步的方式来加载这些脚本,以减少较短的缓存时间带来的影响。

常用的第三方资源通常有不错的表现,但当我们考察更多的资源时,就可以发现这里相当的提升空间。

缓存容量不足 

根据2007年的一项实验(experiment) 40%-60%的用户没有所浏览页面的缓存,其中20%的浏览页面没有本地缓存。

缺少足够缓存的原因很多,我认为其中最重要的原因是过小的缓存容量。下面是我在我自己的设备测试的数据(一些浏览器的缓存大小会基于可用磁盘空间计算,而我的磁盘是250GB,其中54GB可用。):

  • Chrome:320MB
  • Internet Explorer 9:250 MB
  • Firefox 11: 830 MB (about:cache)
  • Opera 11: 20 MB (Preferences | Advanced | History)
  • iPhone 4, iOS 5.1: 30-35 MB (基于测试)
  • Galaxy Nexus: 18 MB (基于测试)

除了Firefox 11比较接近我期望的大小,其它的都太小了。一部钢铁侠2也有1.82GB了,根本不够用。(让浏览器中缓存多媒体文件!!!!!)。

现实的缓存状况 

为了提供让浏览增加缓存容量的依据,必须要获取真实用户的统计数据。为此参与Velocity Summit的各家浏览器团队一起完成了一项课题 。特别推荐Will Chan的提交的这篇Chromium
cache metrics
,里面列出了一些非常有价值的缓存数据。

主要数据有:

  • 近30%用户的缓存完整(320 MB)
  • 对于缓存满的用户,他们平均要花4小的浏览时间(约20小时)才会拥有完整的缓存
  • 7%的用户至少一周清一次缓存
  • 19%用户会一周经历一次"缓存损坏"的错误,然后清掉他们的缓存

最后一项关于缓存损坏的统计非常有趣,我非常欣赏这样的坦率。IE9团队有着相似的数据(something
similar
). IE 7&8 将缓存容量限制在50MB, 因为基于测试当时发现超过50MB并没有提升缓存命中率。而IE9中,他们终于知道更大的缓存容量的确可以改善缓存命中率:

In IE9, we took a much closer look at our cache behaviors to better understand our surprising finding that larger caches were rarely improving our hit rate.
We found a number of functional problems related to what IE treats as cacheable and how the cache cleanup algorithm works
. After fixing these issues, we found larger cache sizes were again resulting in better hit rates, and
as a result, we’ve changed our default cache size algorithm to provide a larger default cache
.


Will也认识到Chrome的320MB缓存限制需要更新。对于拥有完整缓存的用户而言,30%的比例有些偏低。不过用户也许只对少量的页面比较活跃,比如是只看看Gmail和Facebook。建议加一下针对活跃度的统计。很可能一个用户常常浏览大量的网页,虽然拥有满满的缓存,却体验着低效的页面加载时间。

下一步 

浏览器开发者对于改进缓存责无旁贷。1)提升缓存容量就是改进之一,特别是对于移动设备。2)需要提供和缓存容量及用户行为相关的数据。3)更加有效的淘汰算法(比如IE
9′s prioritization based on mime type 
)。 4)更加关注个性化,当用户访问常用页面可以得到更快的体验。

转载请注明出处: http://blog.csdn.net/horkychen  

原文地址: Cache them if you can

参考: <<HTTP缓存>>

时间: 2024-08-27 03:07:54

[WebKit]管好页面缓存的相关文章

利用Spring MVC轻松实现页面缓存

缓存|页面 Spring的MVC是一个非常灵活的框架,可以无缝集成Struts/WebWork以及Velocity/Tapestry等View技术.Spring的DispatherServlet定义极为灵活,由于是开源框架,我们通过源代码,能轻松定制自己的处理流程. 为了实现页面缓存,可以改写DispatherServlet的doService()方法,这里提出一个解决方案: 利用WrappedResponse获得handler处理后的内容,然后缓存起来,这样在下次请求时,可以直接输出缓存内容.

禁止页面缓存的方法

缓存|页面 1, 在jsp或者servlet中加入 <%response.setHeader("Pragma","No-cache");response.setHeader("Cache-Control","no-cache");response.setDateHeader("Expires", 0);%> 2, 在页面中使用HTML标记,如下面: <HEAD><META ht

关于页面缓存清除的方法小结(整理)

缓存|页面      每次上Chinaasp总有不少的网友问及如何使Asp页面刷新,在IIS4的管理下页面的不刷新问题较IIS5严重得多,而且有时确实加入一些控制页面缓存的语句还是不起什么作用.原因我也不是很清楚,去问问微软吧:-)现在我将清除页面缓存的一些方法总结如下:1.在Asp页面首部加入Response.Buffer = True Response.ExpiresAbsolute = Now() - 1 Response.Expires = 0 Response.CacheControl

关于页面缓存清除的方法小结

缓存|页面 每次上Chinaasp总有不少的网友问及如何使Asp页面刷新,在IIS4的管理下页面的不刷新问题较IIS5严重得多,而且有时确实加入一些控制页面缓存的语句还是不起什么作用.原因我也不是很清楚,去问问微软吧:-)现在我将清除页面缓存的一些方法总结如下:1.在Asp页面首部加入Response.Buffer = True Response.ExpiresAbsolute = Now() - 1 Response.Expires = 0 Response.CacheControl = "n

真实世界中的Rails,第2部分: 高级页面缓存

使用 JavaScript 和 cookies 扩展页面缓存 简介:通常,与用户相关的内容不适于使用页面缓存,原因是针对每个用户的内容会有细微的不同. 通过 JavaScript 和 cookies,甚至可以在显示某些自定义用户数据时采用页面缓存.本文将研究 Ruby on Rails 中的高级页面缓存. 有了页面缓存,Rails 就可以不再介入.在某种程度上,这是件好事 ,因为您的确可以获得优秀的性能.Rails 只需创建 HTML 页面,将其放入目录,之后,就可以置之于脑 后.从那时起,就由

ASP.NET:页面缓存

ASP.NET 提供三种主要形式的缓存:页面缓存.用户控件输出缓存和缓存 API. 页面输出缓存作为最简单的缓存形式,将已经生成的动/静太页面全部内容保存在服务器内容中.当再有请求时,系统将缓存中的相关数据直接输出,直到缓存数据过期.在这个过程中,缓存不再要再次经过页面处理生命周期.这样可以缩短请求响应时间,提高应用程序性能.显然,页面输出缓存适用于不需要频繁更新数据,而占用大量时间和资源才能编译生成的页面. 实现页面输出缓存,通常可以用以下两种方法: 一.使用@ OutputCache指令 使

php页面缓存ob系列函数介绍

  这几天接触了phpcms的页面缓存,有些感触.其好处就不多说了,它一般是用在数据库查询较多的页面中,对于插入修改删除的页面就不大合适了 php页面缓存主要用到的是ob系列函数,如ob_start(),ob_end_flush(),ob_get_contents() 下面是编码部分.   1.初始化函数,一般是设置页面缓存路径.缓存文件命名格式等,可按个人喜好自定义.这里用到的识别ID是经加密的$_SERVER[REQUEST_URI]参数.这个函数中最后还有一个if判断:若未过缓存期,则加载

ASP关于页面缓存清除的方法小结

 每次上Chinaasp总有不少的网友问及如何使Asp页面刷新,在IIS4的管理下页面的不刷新问题较IIS5严重得多,而且有时确实加入一些控制页面缓存的语句还是不起什么作用.原因我也不是很清楚,去问问微软吧:-) 现在我将清除页面缓存的一些方法总结如下: 1.在Asp页面首部加入 Response.Buffer = True Response.ExpiresAbsolute = Now() - 1 Response.Expires = 0 Response.CacheControl = "no-

Asp.net禁用页面缓存的方法总结

 这篇文章主要介绍了Asp.net禁用页面缓存的方法,需要的朋友可以参考下 1.在Asp页面首部<head>加入      代码如下:   Response.Buffer   =   True       Response.ExpiresAbsolute   =   Now()   -   1       Response.Expires   =   0       Response.CacheControl   =   "no-cache"       Response.