霜天部落 | 专注PHP研发,研究LAMP高性能架构部署与优化

Ajax性能分析

       由于 Asynchronous JavaScript + XML(Ajax)的出现,用户对交互性和性能的期望越来越高了,而开发人员也把 Ajax 视为 Web 应用程序中必需的部分。随着更多的代码转移到客户端和网络模型的改变,开发人员社区构建了更多工具来解决 Ajax 独特的性能问题。本文讨论如何使用工具集在 Ajax 应用程序中寻找和纠正性能问题。

       性能是促使开发 人员用 Ajax 改进应用程序的主要因素之一。Ajax 可以与服务器进行通信而不必请求完整的页面,因此可以改进响应时间。通过减少响应时间,Ajax 可以提供更好的用户体验。但是,分析和改进 Ajax 应用程序需要一套与传统 Web 应用程序不同的工具。本文讨论这些工具并解释如何使用它们寻找和纠正性能问题。

Ajax 应用程序的性能取决于 Web 应用程序的几个方面:

  • 服务器响应时间
  • 网络传输时间
  • 客户机 JavaScript 的处理时间

在 传统的 Web 应用程序开发中,服务器响应时间是性能分析的主要重点。大多数性能分析度量应用服务器是否能够快速处理请求、执行必需的应用程序逻辑和生成响应。在 Ajax 应用程序开发中,这仍然是应用程序性能的一个重要方面,但是开发人员对这个方面的了解已经很深入了,所以本文主要关注性能的其他方面。

为了了解 Web 应用程序的哪些方面需要改进,必须适当地分析应用程序的组件。本文讨论如何使用 Firefox 的 Firebug 扩展和 YSlow 插件分析 Web 应用程序。安装这些工具之后,连接正在开发的站点并单击 Firefox 状态栏中的 YSlow。这会在 Firebug 中打开 YSlow 界面。现在单击 Performance 按钮。YSlow 对应用程序进行分析,并提供关于应用程序网络传输时间的不同部分的报告,见图 1。

YSlow 报告

YSlow 报告

 在大多数 Web 应用程序中,网络传输时间是主要的瓶颈。可以通过 YSlow 报告分析网络传输的不同方面,了解如何减少传输时间。

每个 HTTP 请求都需要花一些时间发送到服务器并接收响应。即使响应很小,仍然需要基本的往返时间,这称为延迟。YSlow 根据发出的 HTTP 请求数量进行评级。大量的请求会导致装载速度显著降低。可以简化页面,减少需要装载的组件,从而减少 HTTP 请求。可以通过使用 CSS sprites 减少图像请求。获得一些可以生成 CSS sprites 的工具(参见 参考资料 一节)。为了减少脚本和 CSS 请求,可以以内联方式把它们包含在页面中,或者把多个脚本或 CSS 文件组合在一起。

可以提供指定了未来日期的 HTTP 缓存过期头,这会让浏览器对组件进行缓存,因此可以减少 HTTP 请求。当用户在页面之间导航,或者返回您的站点时,可以缓存组件,不需要在每次访问站点时都下载它。如果提供了适当的过期头,代理也可以缓存经常装载的内 容。过期头像下面这样:

Expires: Wed, 10 Mar 2009 10:00:00 GMT

 请记住,如果把过期日期设置为很长时间以后,那么即使已经修改了内容,浏览器仍然会使用缓存的内容。把过期日期设置为一天以后可能比较合适。还可以通过修改文件名使文件名包含版本信息,因此在发布新版本时,就会请求新的 URL,这会让浏览器发出新的请求。可以用 ExpiresDefault 指令配置 Apache,从而添加过期头:

ExpiresDefault "access plus 10 years"

还可以通过 YSlow 检查页面的总下载大小(单击 Stats 按钮)。YSlow 会显示首次访问(没有缓存)时的页面大小和后续页面访问(可以使用缓存)时的页面大小。

HTTP 请求可能涉及多次服务器往返。如果资源使用多个主机或域名,浏览器可能需要多次执行 Domain Name System(DNS)查询。如果必须查询多个名称,YSlow 会发出警告。但是一定要注意,多个 DNS 名称实际上也可能提高性能。大多数浏览器只允许每个主机名有两个连接。但是,通过使用多个主机名,可以建立更多的连接,因此可以进行更多的并发下载。

根据 Wikipedia 上的说法,缩减(minify) 过程就是从源代码中删除所有不必要的字符,但是不改变功能。这些不必要的字符通常包括空格字符、换行字符、注释和块分界符。这些字符用来提高代码的可读性,但是对执行代码而言并不是必要的。

除了减少 HTTP 请求数量之外,减少请求的组件的大小也对性能有好处。可以应用技术手段压缩某些格式。YSlow 会提示哪些技术可以有效地减少响应大小。

通 过消除不必要的空格和注释,可以缩减 JavaScript 代码、CSS 和 HTML。通过改变变量名,可以进一步压缩 JavaScript 代码。Packer 和 YUI 压缩器是有效的 JavaScript 压缩工具,YUI 压缩器也支持对 CSS 进行压缩。还可以用 JavaScript CompressorRater 比较压缩效果(参见 参考资料 一节)。

对 于基于文本的资源,最有效的压缩方法是启用 gzip(GNU zip 的缩写)。通过使用 gzip,一般情况下可以把内容大小减少大约 70%。不要对已经压缩的资源使用 gzip,比如图像和视频。适合使用 gzip 的资源包括 CSS、HTML、JavaScript 代码、XML 和 JavaScript Serialized Object Notation(JSON)。Apache 1.3 通过 mod_gzip 支持 gzip,Apache 2.0 使用 mod_deflate

通过减少资源大小来减小 HTTP 响应是很重要的,但是减小 HTTP 请求也很重要。对于许多因特网用户来说,上传速度比下载速度慢得多,所以性能对请求的大小更敏感。大的 URL、大量提交数据和过多的头都会增加请求的大小。在 Firebug 中,可以在 Net 选项卡上查看请求,见图 2。可以展开每个请求,查看请求头。不必要地增大请求头的常见原因之一是大的 cookie。cookie 包含在每个请求的头中,因此大的 cookie 会显著增加开销。

Firebug Net 面板

Java™ 2 Platform, Enterprise Edition(J2EE)应用程序可以通过一个简单的过滤器 Resource Accelerate 应用这些性能改进技术(缓存过期日期、gzip 和 JavaScript 压缩)。还可以使用 JavaServer Pages(JSP)标记库 pack:tag 对资源进行压缩。还可以选用其他技术,更多信息参见 参考资料 一节。

YSlow 建议的另一种改进技术是使用内容交付网络(CDN)。CDN 提供一个分布式服务器网络,内容放在比较接近最终用户的服务器上,从而改进响应时间。

通 过适当地调整 CSS 和脚本的次序,也可以加快显示 Web 页面的速度。YSlow 会分析 CSS 和脚本声明的位置,并提出改进次序的建议。建议把 CSS 声明放在页面顶部,这样就可以马上使用 CSS 显示页面。把脚本放在页面底部,这样就可以在装载 JavaScript 代码进行交互之前显示页面。

服务器成功地生成 Web 页面并把页面传输给浏览器之后,Ajax 应用程序通常依靠 JavaScript 代码与用户进行交互。大多数用户愿意花一点儿时间等待页面完全下载,但是高品质的交互依赖于页面的迅速反应,所以对页面上各种组件的快速响应是实现良好用 户体验的最重要的方面。另外,在等待下载资源时,浏览器常常仍然有响应能力,但是如果连续执行 JavaScript 代码,有可能完全锁住浏览器。

Firebug 附带一个分析工具。进入 Console 选项卡并单击 Profile, 就可以启动这个分析工具。它可以帮助了解 Web 应用程序的哪些部分大量使用了 JavaScript 代码。如果重复执行相同的操作,这个工具会产生更准确的结果。例如,如果在装载页面时执行大量 JavaScript 代码,那么可以多次装载页面。如果有 JavaScript 鼠标事件处理函数,那么可以把鼠标在页面上移动一段时间,让这个工具收集足够的信息。完成操作之后,单击 Profile 按钮再次显示分析结果,见图 3。
Firebug 分析结果

分析结果列出在分析期间发生的所有函数调用。每个条目显示调用函数的次数和关于函数调用的处理时间的统计数据。Time 列表示等待这个函数返回所花费的总时间量,Own Time 列表示等待这个函数返回所花费的总时间量减去这个函数等待它发出的调用返回的时间。Own time 列通常是最重要的数据,因为它们指出哪些地方发生了耗时很长的处理,而且 Percent 列中的值基于这些数据。在默认情况下,Firebug 按照 Percent 列排序,最高的值放在最上面。耗时最长的调用放在最上面,您可以集中精力改进这些函数的性能。在使用 Firebug 时,很容易访问函数的源代码;只需单击列表中的条目,就会转到那个函数。

在评估 JavaScript 函数的性能时,还要注意调用函数的次数。函数本身可能并不慢(可以查看函数的平均处理时间),但是调用得太频繁了。有时候,不必要地频繁调用一个函数会造成性能问题。例如,onmousemove 等鼠标事件处理函数常常会产生大量调用。

如果发现某个函数花费的处理时间很长,就需要检查 JavaScript 代码,寻找可能存在的问题。表 1 列出一些缓慢的 JavaScript 操作。关于性能基准的更多信息,参见 参考资料 一节。

操作 说明
DOM 访问 与 DOM 的交互常常比普通 JavaScript 代码慢。与 DOM 的交互常常是无法回避的,但是应该尽可能减少。例如,用字符串动态地创建 HTML 并设置 innerHTML 常常比用 DOM 方法创建 HTML 要快。
eval 应该尽可能避免使用 eval 方法,因为脚本运算的开销很大。
with 使用 with 语句创建额外的范围对象,这会减慢变量访问并造成二义性。
for-in 循环 使用传统的 for (var i=0; i<array.length;i++) 循环遍历数组,而不是使用 for-in 循环。不幸的是,大多数 JavaScript 环境中的 for-in 循环实现很慢。

 带 Firebug 和 YSlow 的 Firefox 是分析性能的最佳选择。对于 Mac OS X 上的 Safari,还可以使用 Web Inspector 分析 HTTP 请求。对于 JavaScript 性能分析,可以使用手工技术评估某些函数的性能。手工评估函数的方法是,用 Date 函数度量执行时间,见清单 1:

function myFunctionToTest() { var start = new Date().getTime(); ... // body of the function var totalTime = new Date().getTime() - start;}

 可能影响性能的一个重要问题是 Windows® Internet Explorer® 糟糕的内存管理。随着创建更多的对象和属性,没有应用补丁的 Internet Explorer 6 和更早版本会逐渐变慢。一般来说,如果创建的对象超过 5000 个,旧版本的 Internet Explorer 就非常慢了。

通过使用 Firebug 和 YSlow,可以彻底地分析 Web 应用程序并进行合理的修改来提升性能。YSlow 提供的详细信息有助于减少网络传输时间。Firebug 提供详细的 JavaScript 分析,有助于识别需要改进的代码。这些工具可以帮助开发人员开发性能更好的 Web 应用程序,提供更好的用户体验。