Web性能优化技巧

探究事物的本质似乎是人的天性,凡事总喜欢问个为什么。小时候坐车时会问父母,树为什么会往后面跑,为什么停电了圣斗士就不能看了。很久很久之后,学习了《物理》,仿佛找到答案了,有一种自我满足的快意。

身为程序员,秉持这天性去看待解决性能问题或许就能感觉到一次有趣而有益的挑战吧,没有人知道这条路要走多久,但是,我们在路上。

http协议对并发的建议

http协议中规定了一个特殊规则:浏览器对一个服务器不能同时打开两个以上的连接(IP+Port)。这个规则应该是为了保护服务器不会很容易被洪水攻击。主流浏览器包括IE都实现了这个规则。

DEMO: 用IE下载一个网站的文件,只能同时打开2个,第三个就需要等待。

附注:这个规定是对IE而言是精确到域名而不是IP。


相关内容的详细说明:

HTTP协议1.1中文版:

http://www.cnpaf.net/Class/HTTP/0772522080738754597.html

请查看8.1.4节最后的说明。

其中节选:



使用持续连接的客户机应限制与某一服务器同时连接的个数。单用户客户机不应与任一服务器或代理服务器保持两个以上的连接。代理服务器与其它服务器或代理之间应维护2*N个连接,其中N是同时在线的用户数。设定这一规则是为了改进 HTTP应答时间且避免拥塞。
html加载过程

JQuery之父《精通JavaScrip》中对浏览器加载HTMl过程有一个大致的描述:

# HTML is parsed.

# External scripts/style sheets are loaded.

# Scripts are executed as they are parsed in the document.

# HTML DOM is fully constructed.

# Images and external content are loaded.

# The page is finished loading.

因为HTML没有也不会规定具体如何处理一个html文档的加载过程,因此上文的描述比较粗,没有涉及到一些重要的解析细节,而具体的细节也会因为浏览器的不同而不能一概而论。

这里重点进一步补充说明IE浏览器解析 html文档过程:

# 客户端IE收到的服务器返回的HTML,就开始,顺序读取里面的具体内容,将其解析为RAM中的一棵DOM树。

具体如何解析HTML文档:


1. 顺序读取html文档中的各种元素。


注意点:
因为IE浏览器令人恼火的容错机制,即使html文档不符合规格,也可能被自动纠正,但是可能显示的不是你期望的效果,这可能导致很多隐藏较深的bug。

# 内存中形成一棵DOM树的结构,读到的内容往里面添加。

注意点:此时,并没有显示,只是读成了一个树的结构。

# 如果遇到


1. script有defer 声明,则将可执行语句延迟到整个DOM完全加载完成时执行。

2. script 没有defer声明,立即执行script中的可执行语句。


# 如果遇到External scripts/style sheets, Images and external content等需要下载的资源将其放到特定的结构中。

2.下载1过程中累集的所需要的资源

2.1首先检查缓存中是否存在相关资源,然后依据资源的缓存类型,决定发送那种请求到服务器。

2.1.1 资源在缓存中存在

2.1.1.1 过期类型资源,对比时间,没有过期,不发请求给服务器。

2.1.1.2 客户端缓存类型,发请求到服务器,看资源是否改变。

2.1.1.3 …..

2.1.2资源在缓存中不存在

2.1.2.1优先请求DOM内容可能相关的资源并且执行他们。比如js,,css。最后处理图片等一般资源,原因,性能考虑,避免无用下载。



注意点:1>> 并发下载内容,对同一个服务器,默认不会超过2个,这是由于http1.1协议要求的。http协议这么要求是为了防止单个客户端就占用大量的服务器资源。

2>> 默认情况下,下载是two-by-two进行的,即二个资源二个资源的下载。特定的情况下,静态脚本资源下载会阻塞图片等文件的下载,后文会解释这个。

3>> 协议上不能保证先发出的请求就一定先返回,虽然一般是先发出的先返回。

4>> 当资源文件部分被缓存时,可能出现写在html前面的资源,结果后请求的情况,原因是在请求前会检查ie缓存。

5>> 使用HttpAnalyzer分析html的解析过程,你会发现似乎有时候同时下载的超过了2个,有几种可能:第一种情况是错觉,因为一定有东西被缓存了,此时只需要询问服务器这个文件是否修改,速度很快,好似同时n个。但是要同时下载n个资源,那么服务器必须允许同一个ip的n个端口连接才行,这在 iis服务器是有最大值限制的,通过修改注册表的设置,最大并发可以设置为6个,默认是2个,并且一般情况下不建议修改。第二种情况就是资源被放在了不同的服务器上。


3.绘画内容,即由布局管理器计算DOM树中各个可视元素的位置,高度,等css盒特征。

3.1 当2过程中的与DOM内容可能有关的css,js被下载且被执行后,HTML DOM的内容就已可以绘画了。DirectDraw thread就会开始绘画可视的html元素,可视单元的嵌套越多,绘画就越慢。


注意点:1>> 绘画窗口开始时,可能还有不影响DOM的资源没有下载完。

2>> 源文件Body区域的多个可视标签嵌套,需要所有被嵌套标签都加载完成,才能正常显示,这时候加载顺序是倒着的。举例:
1
2
3
< /div>这段源代码会先显示3,然后2,
最后1。因为加载div1时并没有找到它的结束标签
,于是它不加载继续解析源文件,在找到div2时,和上面一样也没有找到结束位置不做加载。然后是找到div3,div3有结束标签。
浏览器开始加载div3,之后,找到div2的结束标签,加载div2,以次类推,所以这时理论加载顺序为: 3 2 1 。因为IE的容错机制,可以看到上面的例子会比较混乱。

3>> IE可以由特定算法预测部分可视元素的显示。

js下载阻塞图片下载的解决方案

问题描述

在下载完所有的script文件并且执行之前,IE并不知道script中的内容是否包括document.write()这类修改DOM 树的语句或者是 location.href这类跳转语句。如果这些情况发生了,那么IE先前下载的任何资源都可能是白费了。为了避免这种情况发生,IE会首先下载可能影响后续下载的script并且执行它们。这样做的结果就是,js文件的下载会阻塞页面下载进程即使js与图片在不同服务器上,从而影响页面的加载速度。

DEMO

解决办法

将静态js改为动态下载js:


YAHOO网站优化7类别34黄金守则

阅读了网络上google,yahoo的优化原则,感慨万千:"不择手段优化性能,哪怕只是一个byte,1ms能优化的就会优化",优化代码已经溶入了他们的血液和文化。

Yahoo将网站性能优化分为了7个大的类别:内容,服务器,cookie,CSS,JavaScript,Image,Mobile

重点介绍内容这一块的优化守则。

最小化http请求数量 [非常重要]

豹:第一条原则是最重要的原则,也是一个总则。

终端用户响应的时间中,有80%用于下载各项内容。这部分时间包括下载页面中的图像、样式表、脚本、Flash等。通过减少页面中的元素可以减少HTTP请求的次数。这是提高网页速度的关键步骤。

豹:这里yahoo指的是网站类的程序。



减少页面组件的方法其实就是简化页面设计。那么有没有一种方法既能保持页面内容的丰富性又能达到加快响应时间的目的呢?这里有几条减少HTTP请求次数同时又可能保持页面内容丰富的技术。

豹:减少页面组件即减少http请求次数,最关键的是页面设计。


合并文件是通过把所有的脚本放到一个文件中来减少HTTP请求的方法,如可以简单地把所有的CSS文件都放入一个样式表中。当脚本或者样式表在不同页面中使用时需要做不同的修改,这可能会相对麻烦点,但即便如此也要把这个方法作为改善页面性能的重要一步。


CSS Sprites是减少图像请求的有效方法。把所有的背景图像都放到一个图片文件中,然后通过CSS的background- image和background-position属性来显示图片的不同部分;


图片地图是 把多张图片整合到一张图片中。虽然文件的总体大小不会改变,但是可以减少HTTP请求次数。图片地图只有在图片的所有组成部分在页面中是紧挨在一起的时候 才能使用,如导航栏。确定图片的坐标和可能会比较繁琐且容易出错,同时使用图片地图导航也不具有可读性,因此不推荐这种方法;


内联图像是使用data:URL scheme的方法把图像数据加载页面中。这可能会增加页面的大小。把内联图像放到样式表(可缓存)中可以减少HTTP请求同时又避免增加页面文件的大小。但是内联图像现在还没有得到主流浏览器的支持。


减少页面的HTTP请求次数是你首先要做的最重要的一步。这是改进首次访问用户等待时间的最重要的方法。如同Tenni Theurer的他的博客Browser Cahe Usage - Exposed!中所说,HTTP请求在无缓存情况下占去了40%到60%的响应时间。让那些初次访问你网站的人获得更加快速的体验吧!

使用CDN

豹:我们用不上,一种内容分发网络。

向http头添加过期或者缓存控制[重要,且效果明显成本低]

此规则规则主要包含如下两个方面:

# 对于静态网页组件,通过设置足够长的 Expires Header,来实现"永不过期"策略,或者每天过期。

# 对于动态网页组件,通过设置恰当的Cache-Control Header,来帮助浏览器根据条件来判断是否做更新请求。

网络页面设计变得越来越丰富,同时也意味着页面包含越来越多的脚本,样式表,图片和Flash。第一次访问你网站的用户,不得不做多次Http请求,不过你可以通过设置Http的Expires Header让这些组件缓存在客户端,从而在接下来的页面浏览过程中,避免了不必要的Http请求。Expires Header最常用于图片,不过我们更应该将之用到所有的网页组件上:脚本,样式表,Flash等等。

浏览器和代理服务器通过缓存来减少 Http请求的数量和大小,从而更快的加载页面。服务器可以通过在Http response中设置Expires Header来告诉客户端组件应该缓存多长时间。下面是一个足够长的Expires Header,告诉浏览器,这个响应在2010年4月15号前都不过期。

Expires: Thu, 15 Apr 2010 20:00:00 GMT

请记住,如果你已经用了一个相当长的Expires header,在你需要修改一个组件的时候,你一定要同时修改组件的文件名。在Yahoo内部,我们已经将这部分作为构建流程的一部分,具体做法就是为每一个组件设置一个版本号,比如yahoo_2.0.6.js。

足够长的Expires header只会影响已经访问过你网站的那些用户。对那些第一次访问你网站或者已经清除了浏览器缓存的用户,并不能减少Http请求数。所以,此规则对性能的提高依赖于用户点击primed cache页面的频度(Primed Cache是指页面中已经包含了所有组件)。我们测量这条规则对Yahoo的影响,发现大约有75%-85%的页面已经有primed cache。通过设置足够长的Expires header,我们就可以提高缓存在用户浏览器的组件数量,从而在用户接下来的浏览中,不需要通过网络连接中发送一个字节的数据。

豹:使用缓存头和过期header效果是不一样的,使用过期头,可以使得过期之前,IE不再去请求资源,而缓存则必须请求资源是否改变,如果不改变,则不再下载资源,但是依然有一次请求的开销。

至于怎么使用缓存头,有二种方式,一种是在IIS中去配置,一种是重写HttpMoudle加载一个过期header。

用Gzip压缩组件(Gzip Components)[重要,成本低]

豹:许多静态类型的文件,都应该启用Gzip压缩节约网络带宽。

将样式表放在头部(Put Stylesheets at the Top)[准则,没道理不遵守]

将脚本放在底部(Put Scripts at the Bottom)[准则,一旦没有遵守,想去遵守就会很难]


豹:5.5和5.6都与前面html解析过程有密切的关系。

豹:js最佳放置位置

以下列出主要的六种放置情况:

# 直接将Javascript代码放在标记对之间

# 由

你可能感兴趣的:(Web性能优化技巧)