前端性能的测试与优化

测试的目标

做测试的目标是为了让web应用更快,但是由于浏览器的不同。所有的浏览器都做测试是很困难的,并且在chrome这样飞速的浏览器中做测试得到的效果与所付出的时间相比并不是特别合适。一般情况下在最慢的浏览器IE6中达到最好的速度,那么在现代浏览器中也会有不错的速度。

浏览器如何工作

要做详细的测试就需要先了解浏览器是如何工作的!知道了原理才能找到系统的瓶颈,做相应的优化。浏览器的工作流程大致分为如下:

  1. 下载(下载的过程可以细分为:DNS解析、建立连接、发送请求、等待响应、接收数据)。这部分的时间主要消耗在服务器端生成动态html上。
  2. 解析(解析分为:解析、执行、绘制、重绘等过程。且对不同的对象又各有不同,如html/CSS/JS的解析)

纵观浏览器从开始下载到完成绘制(dom loaded)的整个的执行顺序如下:

此图源自W3C,目前已经有一个草案来实现对web应用的测试了:navigation-timing!目前还没有浏览器能支持这个草案。不过此图很好的展示了浏览器的工作流程以及重要的几个点:

  1. domLoading:此项事件触发之前的性能问题大都与网络与服务器程序有很大的关系,前端能做的就是遵守好:34条军规(此军规不仅对domLoading有用,其中一部分对其他过程也有卓越的加速效果!);
  2. domContentLoaded:此项事件标志着dom树解析完成,一般大多数初始化用的JS都从此事件开始;
  3. LoadEventStart:此项事件标志着所有的外部链接都已经载入完成,load事件一般会触发一些不太重要,可以稍后载入的JS;

前端最方便做的就是Processing和onLoad阶段的优化,也就是domLoading事件之后。这就涉及到两个方面的性能测试:CSS和Javascript。不过在测试具体的细节之前先需要找到系统的瓶颈点,也就是整个网页的性能测试。

网页的性能测试

如何测试?

当测试网页的性能时,需要一个开始点。计算此点最方便的就是在html头部添加一段简短的script:

<script>window.startTime = +new Date();</script>

以此来获取开始时间。

接下就是“浏览器开始渲染的时间(Time To Start Render)”。此事件表示浏览器开始绘制页面,而在这之前页面上全是白屏。计算此事件点的关键在于利用document.body.offsetHeight这个属性,即开始绘制的时候body的高度就会有所变化。所以可以通过定时器来查询document.body.offsetHeight,当它大于0时浏览器就开始绘制页面了。这是用户第一次体验到页面正在变化而不是白屏。幸运的是Firefox还提供了一个专有的事件用于表示Time To Start Render:https://developer.mozilla.org/en/Gecko-Specific_DOM_Events。这样就可以得到计算代码为:

if(/Firefox/.test(navigator.userAgent)){
    window.addEventListener("MozAfterPaint", function getStartDate(){
        window.removeEventListener("MozAfterPaint", getStartDate, false);
        window.startRenderTime = new Date()*1;
    }, false);
}
else{
        function getStartDate() {
        if( document.body && document.body.offsetHeight > 0 ){
            window.startRenderTime = new Date()*1;
        }
        setTimeout( getStartDate, 30 );
    }
        getStartDate();
}

接下来的时间点在于domReady时间点,这个点的计算就可以很方便的利用domReady事件完成,对于 IE这样不支持domReady的浏览器也可以用doScroll方法去模仿。一般的库都带有这个功能。 这个时间点意味着dom已经准备好,而且此时页面已经基本绘制出来(当然一些外部资源还没有,例如图片,iframe等)。

之后一个时间点在于onload时间点,这个的计算就更方便了。此时间节点到达意味着浏览器已经结束了html中一开始所表示的外部资源加载完毕,图片都已经可以看到,更重要的一点是浏览器的载入提示已经结束。对很多有些上网年龄的用户来说,这是很直观的一个体验:告诉用户我们的网站已经可以使用了!

最后一个时间点是开始交互时间TTI时间,这个时间的计算则根据不同的网站各有不同,如果是内容性质的网站,TTI时间则应该在domReady之前、Time To Start Render之后。因为内容性质的网站,对用户来说只要看到了内容就表示网站已经可用。如果是交互性质的网站TTI时间则一般在domReady之后(JS的执行一般放在domReady之后)。因为交互性质的网站需要JS去绑定各种事件,然后才能去响应用户的操作。

所有的优化都是为了提高TTI时间,此时间提高的话对用户来说是最直观的网站速度提高的表现。TTI时间点的计算比较特别,因为它因网站而异,一般的方法就是在特定的执行过程中加入一段脚本得到时间:

window.ttiTime = +new Date();

如何优化?

对于Time To Start Render时间的提前,主要的方法如下:

  1. 减少头部中的链接数(合并CSS,缓存favour.ico等待)
  2. 减少html的大小(去掉多余的html,优化结构)
  3. 服务器端更给力

如何优化domReady时间的方法如下:

  1. 脚本放到最后
  2. 将脚本放到domReady之后去执行(这个貌似一般都做得挺好,jQuery普及的基本知识)
  3. 异步的载入JS。同时在domReady之后才开始异步加载,避免在domReady之前脚本就开始执行了
  4. 将JS用wrapper的方式加载,即将JS的载入与执行分开(http://mzhou.me/?p=95284

如何优化onLoad时间点:

  1. 优化之前的几个时间点已经可以达到提前onLoad时间的目的
  2. 分部加载执行JS,将初始化时需要的代码放在domReady时加载执行,将非初始化代码放到onLoad之后执行。例如:加载不重要的第三方插件等等,这些插件多为iframe形式,所以把他们放到onLoad之后再执行最为合适

如何优化TTI:

  1. 做到前面三个优化的时候,已经提高了TTI时间了
  2. 优化CSS效率
  3. 减少dom元素
  4. 优化JS效率
  5. 如果是内容性质的网站,将内容的html放在相对靠前的位置
  6. 如果是交互性质的网站,将特别重要的核心组件的JS剥离出来往前放,加快组件的初始化时间点
  7. 等等

优化TTI的方法较多,因为它的计算方法本身就难以统一的界定出来。

这样差不多你就能找到系统性能瓶颈点了,如何更精确的去定位一些瓶颈呢?这里主要讲一下两个方面:CSS与JS的性能测试

CSS性能测试

为什么要做CSS的性能测试,虽然CSS的解析与性能消耗相比其他来说很少,但是对于一些AJAX操作比较丰富的网站,CSS的性能会影响到重绘的速度,如果实在太慢会进而影响用户的体验。一般这些即使性的重绘操作用户能忍受的最大限度也就在200毫秒左右。加上现在前端模板越来越受到重视,这些大面积的重绘在AJAX web应用中出现的机会会很多。

如何测试?

重置html,简单的说就是将所要测试部分的html去掉,然后再加上。以此来计算CSS的性能。其实更精确的方法是去掉元素相应的选择符(Class,ID等),之所以不这么干是因为这样要操作的dom次数太多,很可能导致计算时间的精度不准。另外一个原因是实际情况中我们不可能去这么修改,更多的是修改innerHTML。测试的代码如下:

//测试整个页面的CSS性能
 
var $body = $('body'),
 
$html = $body.html(),
 
old = + new Date();
 
$body.html($html);
 
console.log( +new Date() - old );

如何优化?

  1. 减少选择符层次(记住选择符是从后面开始查找)
  2. 别用通配选择符*
  3. 减少Dom元素
  4. 减少空的class
  5. background不要平铺
  6. float与position定位虽然好但是如果有第二选择则别用

JavaScript性能测试

相对于CSS,JS的性能测试工具有一大把,因为它导致的问题更严重。这里仅仅推荐几个好用的工具:

  1. dynaTrace: http://ajax.dynatrace.com/ajax/en/Default.aspx
  2. jsperf: http://jsperf.com/
  3. regexbuddy: http://www.regexbuddy.com/
  4. firebug: http://getfirebug.com/
  5. pageSpeed: http://code.google.com/intl/zh-CN/speed/page-speed/
  6. dragonFly:http://www.opera.com/dragonfly/
  7. 如果你知道更多好工具,跪求告诉我!

如何优化?

  1. 减少dom操作次数
  2. 用function wrapper,将执行与加载分离,按需执行
  3. 文章开头也谈到过,只需要为IE6去优化(字符串拼接就是个好例子,在chrome这样告高速浏览器中+号的方法以及和array join的速度一样了,甚至略微超过)
  4. 以循环操作、定时器和连续的事件调用作为优化的重点对象,一般的一次性操作都不会有大问题,但是多次就有问题了。之前twitter就因为在windows.scroll事件的操作中绑定了过多的dom操作而导致浏览器死机
  5. 尽量使用内置函数解决问题,比如高级浏览器都有Array.forEach方法,用于遍历数组
  6. 用局部变量缓存需要多次调用的全局变量
  7. 减少对象查找的层次
  8. 分时优化处理
  9. 查一查你用的库,是不是他们的代码的问题=_=”(http://www.cn-cuckoo.com/deconstructed/jquery.html
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值