性能致胜
高效能程序员的修炼
在Stack Overflow和Stack Exchange上,我们总是非常强调性能。不仅仅因为我们是性能的发烧友(我很内疚),也因为我们认为速度是一个竞争优势。已经有大量的实验数据表明,网站载入和显示的速度越慢,使用它的人就会越少。
Google发现,显示10个结果的网页需要0.4秒来生成,显示30个结果的网页需要0.9秒来生成。半秒钟的延迟会造成20%的流量下降。半秒钟的延迟就扼杀了用户的满意度。
在A/B1测试中,亚马逊试着以100毫秒为单位逐步增加页面的延迟,结果发现即使是非常小的延迟也会付出高昂代价、导致收入显著下跌。
我相信反之亦然。那就是,你的网站越快,就会有越多的人来使用它。如果你像一个信息杂食动物那样思考,这是符合逻辑的:页面载入越快,你就能越快地判断出这个页面是否包含你所需要的内容。因此,你应该永远青睐速度快的网站。在开放的互联网上切换到不同的网站实际上不存在什么机会成本,而且无论你在找什么,那里总是有好些个网站提供类似的体验。于是,你如何把自己跟别人区别开来呢?你得从“快”入手,其他的先放一放。
你是否也感觉到了这个需求——对于速度的需求?如果是这样,我有3个建议想与你分享。
1.虔诚地遵循雅虎的指导原则
自2007年以来,构建一个快速网站的黄金参考准则始终首推雅虎提出的“加速你的网站的13条简单原则2”(英文原文为“Best Practices for Speeding Up Your Web Site”)。不过,这些准则附带了一条告诫:
这里有些不错的建议,但是,其中很多建议只有在你运营了一个每天有几百万独立用户访问的网站时才有意义。你是在运营一个像那样的网站吗?如果答案是肯定的,那你为什么不带着你高雅尊贵的老婆、乘着你的私人飞机去百慕大3群岛度假,还在这里读这个?
我不知该说什么好……自从我4年前写了那篇文章以后,在我身上发生了一件有趣的事情。我现在运营着一个由一系列面向公众、社区驱动的问答网站所组成的网络,而且的确每天有好几百万个独立用户在访问。(但我还没有私人飞机和高雅尊贵的老婆呢……)网站的规模确实是一个考虑因素,但是如果你在运营一个公众网站,你真的应该仔细研读雅虎的那个清单,并且对每一行都用心琢磨一遍。或者你还可以借助于一些工具:
- Yahoo YSlow(http://developer.yahoo.com/yslow)
- Google Page Speed(https://developers.google.com/speed/pagespeed)
- Pingdom Tools(http://tools.pingdom.com/fpt)
我们在很久以前就已经实现了雅虎清单上的那13条原则中的绝大部分,除了有一条,而且是很大的一条:使用CDN(内容分发网络4)。
用户与你的网络服务器的邻近程度直接影响着响应时间。从用户的角度来看,把你的内容部署在多个地理位置分散的服务器上会让你的网页加载得更快。但是,你应该从哪里开始呢?
作为实现根据不同的地理位置来分发内容的第一步,请你不要尝试去重新设计你的网络应用程序以适应分布式架构。根据应用的不同,改变架构可能包括诸如同步会话(session)状态以及在不同位置的服务器之间复制数据库交易数据之类令人望而却步的任务。拉近你的内容和用户之间距离的尝试可能会被改变应用架构这一步延误,甚至永远也无法实现。
记住,有80%~90%的终端用户响应时间都花在下载网页的所有组件上:图片、样式表、脚本、Flash动画等。这个就是关于性能的“黄金法则”。与其从重新设计应用架构这样困难的任务入手,不如首先把你的静态内容分散部署。这样做的话,不仅在响应时间上的改进会更明显,它也能更好地利用CDN的优势使得实现起来更容易。
作为性能优化的最后一步,我们刚刚把我们所有的静态内容都部署到了CDN。结果很令人振奋!这里的参考基线是我们位于纽约市的数据中心。因此,下面这幅图应该被解读为:“我们的网站对于世界各个区域的用户来说,(在使用了不同的内容分发网络之后)速度提升了多少?”
从技术精确的角度来说,静态内容并不是决定性能的全部因素。你还是必须和我们在纽约市的服务器通信,以获得那些动态生成的内容——它们才是网页上真正有用的信息。但是,我们90%的访问者都是匿名的,而且只有36%的流量来自于美国。另外,雅虎的研究表明:有40%~60%的日常访问者的浏览器缓存是空白的。由此可见,针对世界范围内的访问优化利用这种“冷”缓存将带来巨大的效益。
现在,我不会推荐大家直接就上CDN。我宁愿把这一招留着晚一点再使用,因为在雅虎的清单上有一大堆改善性能的做法是免费而且很容易实现的。不过,自2007年以来,使用CDN的成本降低了很多,用起来也简便了很多。这要归功于有更多的公司参与了这个领域的竞争,它们包括亚马逊、NetDNA、CacheFly等。因此,当时机成熟的时候,而且你已经接受我的推荐虔诚地做完了雅虎清单上要求做的事情,你就可以考虑CDN了。
2.善待匿名用户和注册用户(并且为他们进行优化)
我们的问答网站致力于让互联网变得更好。这也是我们将用户贡献的所有内容在“创作共用5”的条款下重新授权回社区的原因所在。不论你是否登录,网站内容永远都是可见的。我鄙视那些用墙围起来的“花园”。事实上,你完全不需要登录就能参与我们的问答。完完全全不需要!
我们的流量主要来源于从搜索引擎或者其他一些地方来的匿名用户。这是典型的“一次创作——可能经过一些编辑——然后被人读上几百万次”的模式。然而,我们也在为热心的社区成员把网站做得更加丰富、富有活力(当然他们一定是登录的)。我们一直都在增加新的特性,这也意味着我们生成了更多的JavaScript和HTML。在每天都访问网站的用户和每个月或者每年只访问一次的用户之间,他们对网站内容的需求不可避免地存在着差异。
这两类用户都是非常重要的。但是,他们的需求有着根本性的不同。匿名用户一心只想快速浏览(获取内容),而我们热心的社区成员是推动网络进步的所有出色内容的创作者。这些小伙子们(和姑娘们)相互帮助;他们值得我们去特别对待。我们为两种类型的用户(匿名用户和登录用户)都精心设计并且为他们进行优化。下面,让我随机挑选一个关于超级用户的问题,我们一起来看看Google Chrome网络控制面板对这个问题的跟踪信息:
我们为匿名用户将HTML,CSS以及JavaScript的数据量降到了最小,这样他们获取网页的速度甚至(比登录的用户)更快。我们把非常基本的功能以存根的形式载入,并且动态地“激活”。举例来说,只有当用户把焦点放在答案输入区域时,编辑功能才会被激活。对于登录的用户而言,下载的数据量必然会大一些,但是我们也可以随意地为我们最热心的社区用户增加特性,而不必担心会影响为数众多但又一言不发的匿名用户的体验。
3.使性能成为一种(公开的)骄傲
到这里,我们已经把雅虎提出的性能指导原则“折腾”完了,并且确信我们为匿名用户进行了优化——我们到哪里还能找到提升性能的空间呢?当然是回到我们的代码。
对于网站的性能,有一个基本的宇宙法则是无法被绕过的:你永远不可能在服务器完成渲染之前发出一个网页。我知道,你可能很不屑。但是我要告诉你,在一段长时间的开发过程中(一年左右),你很容易就会忽略这里或那里的几百毫秒延时,而当有一天你回过头去看的时候,你会发现网页在服务器上的渲染几乎反常地花掉了整整一秒钟。在你的网页的第一个字节被传入网线之前,它居然要在“洞”里待上整整一秒钟——这是一个重大的缺陷!
这就不难理解:作为一名开发者,你要始终把每个页面的性能指标放在你的正前方。这也正是我们用MVC Mini Profiler(http://miniprofiler.com)所做的事情;我们还把它作为一个开源软件回馈给了这个世界。把渲染时间放在我们所发送的每个页面的右上角,这个简单的做法迫使我们去修正所有性能方面的退化和疏忽。
(值得注意的是,你可以点击上面的SQL链接来查看具体有什么操作被运行了,以及每一步所花的时间。你还可以点击share链接来把这次运行的分析数据分享给你的开发者同伴们,这样可以刺激他们去诊断某个特定的问题。这个工具还能处理多个AJAX请求。我有没有提到过,我们这个开源的MVC Mini Profiler简直棒极了?如果你是.NET平台上的开发者,你真的应该去试试。)
事实上,随着渲染时间显示在每一个页面上,并且团队里的每一位成员都能看到,性能就变成了一种骄傲。在很多地方我们只是粗心了点,或者疏忽了一些细微的东西,结果把网页搞得非常慢。大多数性能问题的修正都是微不足道的;即使是那些并不简单的修正,也给了我们极好的机会去重做架构设计,并帮我们所有的用户把事情变得更简单、更快速。
它起作用了吗?当然!就跟你钟爱的ILAsm6一样,它很有用!
这是Google 爬虫程序测出来的页面下载所需的时间——Google推出了一个实验性质的网站性能测试页面(如今已被撤销),号称可以完整地反映出全页面浏览器的载入时间——其数据印证了我们网站性能的提升。
虽然服务器端的页面渲染时间只是决定性能的众多因素中的一个,但它是你开始优化性能的基线。把页面的渲染时间显示在页面上这个简单的做法,实实在在地帮助我们(整个开发团队)构建了超快的网站——它的功劳我再三强调都不过分。相对而言,我们的网站总是快的。但纵然像我们这样向来以“快”见称的网站,在采取了这个简单的做法之后,我都感觉到了它为我们的性能带来的巨大提升。
我不想骗大家。提升性能并不容易。我们达到现在这个水准经过了一段很长而且很艰难的路,我们还花了很多钱去购买非常出色的硬件以运行我们所有的应用。不过,我认为我们的硬件选择还没有到特别奢侈的地步。郑重声明:我确实采纳了我自己的建议7。
我很清楚地记得在2000年的时候从AltaVista换到了Google,在很大程度上是因为Google太快了。对我而言,性能是一个特性(能助我克敌制胜)。我就是更喜欢使用快速的网站(而不是那些速度慢的网站)。自然而然,我要创建一个我自己想用的网站。在这里,我想我们还应该学到一个教训——在开放的互联网世界里竞争,最后只会剩下两种网站:要么很快,要么已经死去。
你将何去何从?