一、性能测试的背景知识
对web应用前端性能的研究并不为了准确地得到一个 响应时间数据,实际上,web性能一部分取决于web服务器和应用服务器(建立连接、下载资源文件),另一部分取决于浏览器的实现机制、web页面上的JS文件的执行等。取决于web服务器和应用服务器的响应时间而与服务器的负载、压力等相关;而取决于浏览器实现机制与JS文件执行所需要的时间则几乎与服务端的负载和压力无关。后者是web前端性能测试的主要目标。
http协议用于传送www方式的数据,该协议采用了请求/响应模型。http协议本身是一种面向非连接的协议,每个Http请求之间都是独立的。每一个http请求都会经历一个“建立连接-请求页面或资源-获利页面或资源-断开连接”的过程。
表1 请求报文格式
请求行(method[分隔符]request-uri[分隔符]http-versionCRLF | 通用信息头 | 请求头 | 实体头 | 报文主体 |
- method包括OPTEIONS、GET、HEAD、POST、PUT、DELETE、和TRACE(以上method者是大小写敏感的)。GET方法取回由request-url标识的信息;HEAD是取回由request-uri标识的信息,只是可以在响应时不返回消息体。POST方法可以请求服务器接收包含在请求中的实体信息,可以用于提交表彰等发送消息。
- CRLF表示换行回车符
- 报文主体:包含了http请求的内容。对于GET等方法来说,报文主体为空;对于POST方法来说,报文主体则包含需要发送给服务器的数据。
表2 响应报文格式
状态行(状态码 原因分析) | 通用信息头 | 响应头 | 实体头 | 报文主体 |
- 状态行由状态码和原因分析两部分构成。状态码由3位数字组成,表示请求是否被理解或被满足;原因分析是对原文的状态码作简短的描述,用来供用户使用。
- 1XX: 信息响应类,表示接收到请求并且继续处理
- 2XX:处理成功响应类,表示运作被成功接收、理解和接受
- 3XX:重定向响应类,表示为了完成指定的运作,必须接受进一步处理
- 4XX:客户端错误,表示客户请求包含语法错误或不能正确执行
- 5XX:服务端错误,表示服务器不能正确执行一个正确的请求
可使用firebug(firefox)/chrome自带的开发者工具(chrome)和HttpWatch(IE、firefox)等工具来进行前端性能的测试。另外,apache benchmark(ab)也可帮助获取网站的响应时间。利用这些工具,可查看到访问某个域名时,浏览器与服务器之间的数据交互。其中,有些数据包的头信息与前端性能息息相关。
- accept-encoding:是浏览器发出的请求头中包含的头信息域之一,用于告诉服务器所接受的页面文件的编码方式,如accept-encoding:gzip, deflate就告诉服务器,浏览器能够接受不压缩和使用gzip压缩两种方式的页面内容。经过压缩的页面内容能节省传输所用的时间,缩短响应时间。
- connection:Http协议虽然是面向非连接的、无状态的协议,但建立和断开连接也需要消耗一定的时间和资源。对于非常小的页面和资源文件来说,很可能建立连接所消耗的时间甚至大于页面或资源的处理时间。为了让响应时间尽可能缩短,http协议引入了持久连接。如果浏览器与服务器约定了持久连接,当某个资源文件或是html文件传输完成后,连接并不立即关闭,而是等待一段时间内没有任何传输需要发生时,才关闭该连接。当connection的值为keep-alive时,浏览器与服务器之间约定使用持久连接。
- expires:该域的值用于指示返回数据的到期时间。在到时期间来临前,当用户再次访问该url时,浏览器将会从缓存中读取该url的部分内容。当当前时间大于expires指定的时间时,浏览器向服务器发送请求获取该url资源。
二、浏览器打开URL的方式
浏览器的核心是浏览器引擎,目前市场占有率最训折几种浏览器几乎都使用了不同的浏览器引擎:IE使用的是Trident、Firefox使用的是Gecko、Safari和Chrome使用的则是Webkit。不同的浏览器引擎对W3C的规范支持不尽相同,在具体功能的实现上也不完全一致。
浏览器从输入URL地址开始到页面完全可用的大致过程如下:1. 连接到URL所在服务器 2. 获取页面对应的HTML文档 3.解析文档并获取所需要的资源 4.页面上的JS文件与CSS文件 5. onload事件。
- 连接到URL所在服务器。浏览器在得到一个URL后,会首先通过向DNS服务器请求“翻译”所在网站的IP地址。然后,浏览器向该地址发起连接请求,建立到服务器的连接。
- 当连接建立后,浏览器向服务器发送HTTP请求,请求URL对应的HTML文档。不管请求的URL是一个静态的HTML文件,不审一个动态脚本(ASPX、PHP或JSP),服务器返回给浏览器的一定是一个HTML文档。该HTML文档就是浏览器需要呈现的页面。
- 浏览器在获取HTML文档后会对文档进行解析,目的是知道该页面需要哪些资源以及生成DOM树。生成DOM树的工作与下载页面上需要的其他资源同时进行。大致来说,浏览器会逐行分析HTML文档,一旦发现象一个标签,应付以根据标签的要求分配对指定资源的下载。为了提高展现速度,浏览器通常会发起多个连接,并行下载HTML中的元件;但由于web服务器能力有限,且需要服务尽可能多的用户,所以会限制单个浏览器的最大连接数。但并非所有的元件都可被并行下载。一般情况下,页面中如果直接使用<script>标签标识的内嵌的JS语句,或引用外部的JS文件,浏览器需要按照JS遵循其在HTML文档中的顺序来执行JS。在较早的浏览器(如IE6/IE7,firefox3.5以前的版本)中,当下载JS文件时,浏览器才继续下载页面上的其他资源。
- 页面中的JS文件和CSS文件的处理需要特殊对待。如3中所述,对浏览器而言,在处理页面上的JS文件或JS代码时,只需要保证以下两点:1)所胡JS代码按照其在HTML文档中出现的顺序执行,这样可以保证JS文件之间存在的依赖关系在执行时不会被破坏。2)JS文件在执行时,其依赖的DOM树已经对立好。不同的浏览器采用不同中的策略保证这两点。CSS一般用于控制页面元素的显示效果,当DOM树上某个元素被CSS修改后,浏览器可能需要对页面的局部或全部进行重绘。为了避免重绘带来的闪烁等不好的用户体验,不同的浏览器会采用不同的方法决定何时开始在屏幕上绘出页面。大体上说,当HTML文档被下载后,浏览器一边解析HTML文档,一边开始下载页面上的资源,一旦某个资源下载完成后,浏览器就能够开始在页面上渲染该资源元素。如果此后 某外部样式表文件被加载,浏览器则会根据外部样式表文件的内容重新渲染页面元素。正因为这样,有些浏览器会在获利可用的样式表文件之前阻止页面内容在屏幕上的显示。这也就是为什么许多不慌不忙前端性能相关的文献中建议把对样式表的引用放在HTML文档的最前面的原因。
- 当HTML文档解析完成,生成了DOM树,所有页面需要的资源文件(非JS文件)都已经成功下载执行后,浏览器会发出Onload事件并回调HTML文档中的onload函数。对浏览器来说,Onload事件是最接近页面就绪的事件。但是,onload执行完成并不标志着页面已经完全就绪,页面上可能还有一些JS脚本需要在其后运行。
三、提高前端性能的方法
要提升前端性能,在两套思路:1。减少页面加载所需要的时间 2。提升用户的观感,让用户觉得页面更快。减少页面加载所需时间,可以从请求的数量、请求的并发度及网络传输时间等方面来着手;而提升用户观感,则主要从让页面尽快开始显示入手。
- 使用DNS缓存技术。当然,一般而言,由于浏览器本身有一定的DNS缓存机制,通常情况下,服务端的DNS缓存并不能带来太大的性能提升。
- 减小需要传输文件的尺寸。减少需要传输文件的尺寸是一个提升性能的方法。在网络带宽有限的情况下,这种方法能带来巨大的好处。可使用压缩页面、使用混淆等方法减少JS和样式表的大小、从JS文件和样式表中去除不需要使用的部分等,都可以直到减小需要传输文件尺寸的作用。
- 加快文件传输速度。Internet用户分布在一个较广阔的区域中,可使用CDN(Content Delivery Network)技术、在联通/移动/电信等运营商都设置GDN服务器等,让用户尽可能访问到对用户节点而言更快速的服务器就可以加快文件传输速度。
- 减少发送的请求数量。请求的建议会耗费一定的时间和资源,即使使用持久连续方式,由于浏览器与每个服务器之间建立的持久连接数量是有限的,减少非必须的数量也能给性能提升带来帮助。可利用浏览器缓存、使用合并的图片文件等方法来减少发送的请求数量。
- 提高浏览器下载的并发度。有些浏览器中,下载JS文件会阻塞其他文件的下载,所以可以将JS文件放置在HTML文档的最后提高浏览器的下载并发度。另外,服务器会限制浏览器的最大连接数,所以若使用多个域名等方法来提供不同的页面内容,就可变相地提高浏览器的下载并发度,有利于更快地展现页面。
- 让页面尽早开始显示。JS文件和样式表在不同浏览器上对性能有不同的影响。但有些通用的原则可用来尽快地展示页面。如,将样式表的引用放在HTML文档的开头。这样,当样式表在下载完成后,浏览器就可以开始在屏幕上显示页面元素了。另个,可将JS的引用放在HTML的最后。这样,JS下载和执行会在所有页面都下载完成之后,不会阻止其他页面元素的显示,从用户观感上来说,JS文件的下载和执行时间完全不会被用户感觉到。