缓存为王

前面我写了一篇快速web app的关键是使用Ajax、优化Javascript和更好的缓存。

  • 使用Ajax可以减少网络流量到只有少量的JSON请求。
  • 优化Javascript(异步下载脚本、分组DOM修改、对UI进程作出让步等)允许请求可以并行然后快速渲染。
  • 更好的缓存意味着web app的大部分资源是存储在本地,然后并不会再有任何http请求了。

理解每种技术在哪里发挥作用很重要。使用Ajax,例如,不会让页面初始化加载更快(而且常常会不小心让它更慢),但是后面的“页面”(用户操作)会更爽。另一方面,优化Javascript,会让初始页面和后面的页面都更快,更好的缓存则位于中间:第一次访问不快,但后面的访问会更快。同时,即便在用户关掉浏览器之后再一次返回你的网站时初始化页面也会更快——这样性能优势要胜过浏览器会话(sessions)。

这些网站性能优化并不是互斥的——你应该都使用!但我(或者你也)想知道哪一个才有最大的效果呢?所以我进行了一次测试来测量这些不同的因素。我想要看看它们在实际网站中的效果,所以我使用了WebPagetest,这里我可以很方便的在Alexa排名前1000的网站中做一些测试。由于并没有办法让一个网站直接“Ajax化”,所以我决定专注与网络使用的时间。最后,我做了下面4项测试:

  • 基准——用IE9和一个模拟的DSL连接速度(1.5Mbps下载、384Kbps上传,50ms RTT)来运行Alexa排名前1000的网站。每个URL加载3次取中间值(基于页面加载时间)作为最终结果。只看“第一次”(无缓存)的页面加载。
  • 快速网络——除了使用一个模拟的FIOS网络(20Mbps下载,5Mbps上行,4ms RTT)以外和基准测试一致。
  • 无JavaScript——同基准测试一样,只是这次在RESTful API 上使用了“noscript”选项。效果和在浏览器中禁用JavaScript一致。这并不是一个对“优化JavaScript”的完美替代,因为所有的JavaScript产生的HTTP请求都被跳过了,另一方面,所有在noscript标签里面的资源——如果有的话——又被加了进来。我们后面会对比HTTP请求数。
  • 缓存模式——除了在“重复模式”下浏览以外其它和基准测试一致。这个测试用来看在今天给到缓存头(caching headers)的优势的最佳情况。然而并不是任何东西都可以缓存的,所以还是会有些网络请求发生。

哪个测试会产生最快的页面加载时间呢?思考一下然后写下你的猜测。我在开始测试前也猜测了一下,然后结果是我猜错了。。。

结果:

这个表显示了中间值和每个测试的window.onload时间的第95个百分位。基准测试的中间加载时间是7.65秒(95百分位是24.88)。每个优化都非常明显的让页面加载快了。下面是它们的对比:

  • 缓存模式是测试中最快的,3.46秒(95百分位是12.00).
  • 快速网络是第二快的,4.13秒 (95百分位是13.28).
  • 无JavaScript第三,4.74秒(95百分位是15.76).

我很惊讶无JavaScript竟然不是最快的。禁用JavaScript移除在下载资源时可能发生的阻塞行为。尽管IE9中脚本和其它大部分资源一起并行下载(请看Browserscope),它们也会引起阻塞字体文件或者其它边界情况。更重要地,禁用JavaScript减少了请求数量——从基准测试的90个降到59个,总请求大小也从927kb降到577kb。

快速网络的提升也超出了我的期待。请求的数量和带宽大小和基准测试一致,但是加载时间的中间值竟快了46%,从7.65秒降到4.13秒。这表明网络环境(连接速度和延迟)会有明显的影响。(难怪创建一个快速的移动网络体验很难。)
缓存赢得测试的关键是,请求数从90降到了32。有58个请求是从本地缓存读取的——而没有任何HTTP流量。HTTP Archive的关于Alexa 前1000名网站的 max-age表显示,59%的请求被配置了缓存(max-age > 0)。它们中的大部分有比较短的不超过10分钟的缓存时间,但是由于“重复浏览”是立刻进行的,所以它们是从缓存中读取的——所以它确实是一个最佳案例了。90的59%是53。另外的5个请求貌似由于启发式缓存(heuristic caching)而被从缓存中丢掉了。


尽管结果很意外,但我很高兴缓存被证明是如此有效的让网站更快的因素(或许也是最有效的因素)。我最近开始关注缓存。这是一个重要的开端——提高认识我们面前的谎言的机会。

仅仅使用今天的缓存头部,资源请求数量就减少了64%。但也只是“重复浏览”是立即进行的。如果我们等待了一天,19%的缓存就过期了,又会产生17个新的If-Modified-Since请求。貌似那5个启发式缓存也会产生新的请求。所以我们需要换个方向让更多的资源缓存更长的时间。然后,要得到快速加载资源的优势的话我们需要调查预读资源——甚至在浏览器请求它们之前——的方法。

PS:表示不太懂文中的“第95个百分点”(95th percentile),求高人解答

文章译自:Cache is King
中文原文:缓存为王
请尊重版权,转载请注明来源,多谢