|
|
|
|
移动端

jQuery应用程序性能指标和调优

文章介绍了jQuery代码性能的最佳实践,充分利用运行得最快的代码部分,而尽量避免运行得最慢的代码部分。在您阅读完本文之后,“jQuery的性能好吗”这个问题将得到解答。

作者:Michael来源:IBM DW|2010-07-28 09:25

技术沙龙 | 4月21日多位区块链专家进行区块链技术应用场景解读!


jQuery无疑是一个出色的JavaScript库,但它的性能如何?在其易用性和优异Web页面性能之间进行折衷是否值得?它的性能是不是真的很优异?本文将回答关于jQuery性能的问题,并提供一些可以改进应用程序性能的技巧。

51CTO推荐专题: jQuery从入门到精通

度量JavaScript性能要考虑的最重要问题是执行JavaScript的环境。因为代码是运行在客户端上的,所以它的执行依赖于客户端计算机,这使得客户端机器成为影响性能的最重要因素。很明显,运行4核CPU的新服务器执行代码的速度肯定要比400MHz老式处理器快。这是毫无疑问的。不过,由于您不能控制Web应用程序用户用于访问您的站点的机器,所以在度量性能时要考虑关于硬件的许多因素。

JavaScript性能的另一个重要方面是用于运行JavaScript的浏览器,JavaScript新手可能不容易发觉这个影响因素。每个浏览器内部都包含一个JavaScript引擎,即用于解析和执行JavaScript代码并处理Web应用程序页面的本机代码。因此,JavaScript的性能严重依赖于客户端使用的浏览器,并且在某些情况下,您可以控制用户使用的浏览器。本文提供一些关于JavaScript性能的指导原则,并解释不同浏览器对性能的影响。

创建性能测试

关于性能测试的第一步是创建一个合适的性能测试。jQuery以及其他JavaScript库在代码中扮演的最重要角色就是使用选择查找特定页面元素。我在最初的性能测试中就以这方面为重点。一个良好的性能测试应该真正地发挥JavaScript库的全部力量,用包含数千个页面元素的页面测试它。应该运行所有选择方法,让我看到哪个选择方法最快,哪个最慢。测试应该事先知道正确的答案,从而确定JavaScript库是否正确地执行选择方法。最后,应该显示所有结果,并附带所用的运行时间,让我能够在所有库之间进行比较。

我差点忽略了性能测试的最重要方面:它应该是免费的。毕竟这个系列文章的不成文规则就是相互利用彼此的成果,因此我继续发扬这种精神,在此使用一个现成的JavaScript库性能测试。这个测试称为SlickSpeedSelectorsTest,它非常适合我的需求。它将jQuery1.2.6(撰写本文时的最新版本)与其他4个流行的JavaScript库(MooTools、Prototype、YUI和Dojo)进行比较。然后,它使用带有数千个页面元素的页面运行40个选择测试。换句话说,这是我所希望的最佳性能测试。我将在第一个性能测试分析中使用该测试。

对比JavaScript库的性能

对于第一个性能测试,我使用的运行环境是2.2GHz处理器、2GBRAM和Firefox3.0.3(非常重要)。我在该配置下运行5次测试,图1显示了5次运行的平均结果。

性能测试1的结果 
图 1.性能测试1的结果

从第一次测试能够得出什么结论?现在我们仅关注总体结果,而不是每次测试。在获得一些总体结论之后,我将稍后在本文中关注每个测试。

结论1:YUI慢到了极点

对,与其他库相比,YUI真的很慢。仔细查看每个测试,找出为什么这个库在选择元素组(例如“p,a”)时非常慢。对于要求具有很好性能的页面而言,这个库是最差的选择。

结论2:Mootools、jQuery和Dojo的运行时间几乎一样

与其他两个库相比,这3个库是非常快的,并且Dojo是它们当中最快的,而jQuery是最慢的。但是从全局考虑,它们之间的速度是很接近的。

结论3:这些库之间的相对差别还是比较明显的

度量最快时间/最慢时间以确定速度的相对差别,您可以看到相对差别为332%。这个差别是比较大的,这表明使用Firefox时选择不同的JavaScript库会对性能有影响。
但是要记住,这些结论仅基于一个浏览器的结果。这是基于Firefox3.0.3得出的结论。现在我们进入下一小节,我将在不同的浏览器上运行该测试。

在不同浏览器上的JavaScript性能

面对不同浏览器运行JavaScript会得出的不同结果(性能和时间都不同),许多初级Web程序员觉得不可思议。尽管这对初级Web程序员而言是个挫折(他们担心要编写额外的代码来处理不同的浏览器),但是有经验的Web程序员在Netscape和InternetExplorer的早期就知道如何处理该问题。这也是使用JavaScript库的一个亮点,因为它们都谨慎处理许多或大部分浏览器差异。

JavaScript速度差异的主要原因是每个浏览器都使用自己的JavaScript引擎。JavaScript引擎是用于解析JavaScript并根据Web应用程序执行它的本机代码。因此,JavaScript的执行速度与底层引擎直接相关。在最近几个月,许多浏览器公司越来越关注他们的浏览器的性能,这是有原因的。随着某些页面的JavaScript变得日益复杂,JavaScript引擎的快慢能够影响Web应用程序的响应速度。因此,当Google和Firefox等公司谈论它们的JavaScript引擎时,它们就会谈及下一代引擎的速度要快10倍。这对Web应用程序而言是很重要的,因为底层JavaScript引擎的速度直接导致更复杂的Web应用程序的出现。

现在,您知道JavaScript引擎是JavaScript执行速度的一个因素,那么让我们在不同的浏览器上运行刚才在Firefox上运行的测试,并尝试找出不同的引擎对JavaScript性能的影响。记住,这个测试与我前面在Firefox上运行的测试是一样的,因此除了JavaScript引擎以外,其他所有东西都是相同的。图2显示了测试结果。

测试结果 
图2. 性能测试2的结果

看完这些测试结果之后,您首先注意到的是在这些浏览器中运行得到的时间差很大。在Chrome1.0上运行jQuery需要168毫秒,而在IE6上运行需要1728秒。这是难以置信的时间差!jQuery选择方法在IE6上运行比在Chrome上运行慢10倍!现在,您知道为什么Google喜欢夸耀它的JavaScript引擎,以及为什么某些浏览器很少介绍自己的JavaScript引擎。这些差别还是比较大的。

您应该注意到,jQuery在Firefox或一些其他浏览器上运行时速度排在第3位,而在另一些浏览器上排在第1位。事实上,这些结果表明,根据性能进行分类的话,这些库可以分为两组,而不管使用什么浏览器。Mootools、Dojo和jQuery通常属于一个组别,而Prototype和YUI属于另一个组别,前一组要比后一组快得多。

性能测试结论

我觉得所有这些结论都需要专门花一个小节进行阐述,因为它们对JavaScript开发人员非常重要。我仍然尝试总结上面的性能结果,并且没有忘记本文是以jQuery为主题的。

结论1:Mootools、jQuery和Dojo在性能方面不分上下

图3. 测试结果的平均值(Mootools、jQuery 和 Dojo) 
图3. 测试结果的平均值(Mootools、jQuery 和 Dojo)

查看它们在所有5个浏览器上进行的测试,在求取平均值之后,您可以看到这3个库的性能几乎是一样的。(理想情况下,我们应该调查每个浏览器的市场份额。但是调整这些数字很难,因为使用JavaScript库的站点不一定由“平均用户”访问)。

结论2:Prototype和YUI的性能很慢

看看这两个库在5个浏览器中的测试结果与jQuery的对比。在求取它们的平均值之后,您可以发现这两个库的性能差别有多大。它们在任意浏览器中平均比jQuery慢300%。

图4. 测试结果的平均值(jQuery、Prototype 和 YUI) 
图4. 测试结果的平均值(jQuery、Prototype 和 YUI)

结论3:如果对性能要求比较高时,选择Mootools、jQuery和Dojo之一获得的性能几乎一样

根据以上的平均值,选择这3个库之一比选择另外两个库之一能够获得更多的性能优势。从在所有浏览器上运行得出的平均值看,它们的性能是相当的。因此,当您选择JavaScript库时,选择这3个库之一是不会错的。

结论4:如果对性能要求比较高时,不要选择Prototype或YUI

如果要求JavaScript库具有较高的性能,或者打算创建一个大型的JavaScript项目,那么就不应该选择这两个库之一。这两个库的性能要比其他库逊色得多。

结论5:浏览器对性能的影响是JavaScript库的9倍

我认为这是本文所有结论中最重要的结论。您可以在特定情况下讨论哪个JavaScript库最快,但它最终的影响却是很小的!对于性能而言,浏览器的影响比库本身要大得多。回顾一下图3和图4的平均值,您可以看到3个最快的库中,最慢那个(Dojo)仅比最快那个(jQuery)慢15%。只有15%!

然而,您看看jQuery在最快的浏览器(Chrome1.0)和最慢的浏览器(IE6)上运行的速度差别,这个差别竟然达到1000%!从这两个数字看,15%对1000%而言是微不足道的。至此,关于3个较快的库中哪个是最快的争论可以停止了,因为它们对最终结果的影响是微乎其微的。

结论6:如果JavaScript性能对Web应用程序很重要,并且您可以控制选择什么浏览器,那么就选择最快的浏览器

在某些情况下,您可以控制使用什么浏览器访问站点。如果能够控制使用什么浏览器,那么您就是很幸运的。我就碰到这样幸运的项目。在这种情况下,如果您拥有一个复杂的JavaScript应用程序,或者您认为性能很重要,那么您就应该控制用户用于访问Web应用程序的浏览器。这些测试已经清楚地显示了浏览器的影响。如果您的JavaScript应用程序的访问量很大,那么您可以告诉用户,他们必须使用Chrome。

结论7:如果您不能控制用户使用的浏览器,那么要首先考虑在IE6上的性能

但是,在大部分情况下,我们都无法控制用户使用什么浏览器访问我们的站点。不过,很大一部分用户都使用IE6浏览网页。到目前为止的测试中,这个浏览器的JavaScript引擎是最慢的。但是由于仍然有大量用户使用它,并且良好的Web设计需要“适应最糟糕的情况”,这意味着您可以考虑根据IE6设计您的JavaScript应用程序。

jQuery性能调优

本文的第二部分将讨论如何改进jQuery代码的性能。前一部分表明选择jQuery作为JavaScript库指向了正确的性能方向。如果您正在阅读本文,您可能已经使用了jQuery。但是底层库速度快并不意味着您编写的所有代码都是高质量的。如果您没有回过头来想想应该怎么做,使用jQuery仍然会编写出非常慢的代码。

这个部分介绍一些性能调优知识,以及改进jQuery代码速度的最佳实践技巧。

技巧#1-尽可能多地通过ID进行搜索,而不是CLASS

图5. ID搜索和CLASS搜索对比 
图5. ID搜索和CLASS搜索对比

在jQuery代码中两种常见的搜索技术是通过元素的ID进行搜索和通过元素的CLASS进行搜索。在使用常规JavaScript的JavaScript库之前,通过ID查找页面元素还是相当简单的。可以使用getElementById()方法快速找到元素。但是如果没有JavaScript库,要查找CLASS会更加困难,在必要情况下,我们还通过在其ID中进行编码帮助查找。

使用jQuery时,搜索CLASS就像搜索页面上的ID一样简单,因此这两个搜索似乎是可互换的。然而实际情况并非如此。通过ID搜索比通过CLASS搜索要快得多。当通过ID进行搜索时,jQuery实际上仅使用内置的getElementById()方法,但通过CLASS进行搜索时必须遍历页面上的所有元素,以查找匹配项。很明显,当页面越大并且越复杂时,通过CLASS进行搜索会导致响应非常慢,而通过ID进行搜索不会随着页面变大而变慢。

前面运行的jQuery性能测试结果支持这一数据。让我们查看每个测试,看看需要注意jQuery代码的什么地方。在这个例子中,分别看看通过ID和CLASS进行搜索时的测试结果。

这些测试是不同的,但它们得出的数据表明通过ID进行搜索比通过CLASS进行搜索快得多。这如何影响到jQuery代码?在编写搜索时,您要记住这些技巧:如果既可选择CLASS又可选择ID,那么通常要选择ID。如果需要在您的代码中搜索某些元素,一定要给它们分配ID。清单1显示了一个实际的jQuery测试,您可以在您的机器上运行它对此进行验证:

  1. $(document).ready(function(){  
  2. console.info("StartTest");  
  3. vard=newDate();  
  4. console.info(d.getSeconds()+""+d.getMilliseconds());  
  5. vartestBody="";  
  6. for(vari=0;i<1000;i++)  
  7. {  
  8. testBody+="<divclassdivclass='testable"+i+"'>";  
  9. }  
  10. $("body").append(testBody);  
  11. for(vari=0;i<1000;i++)  
  12. {  
  13. $(".testable"+i);  
  14. }  
  15.  
  16. vard=newDate();  
  17. console.info(d.getSeconds()+""+d.getMilliseconds());  
  18. console.time("StartIDTest");  
  19.  
  20. testBody="";  
  21. for(vari=0;i<1000;i++)  
  22. {  
  23. testBody+="<dividdivid='testable"+i+"'>";  
  24. }  
  25. $("body").append(testBody);  
  26. for(vari=0;i<1000;i++)  
  27. {  
  28. $("#testable"+i);  
  29. }  
  30. vard=newDate();  
  31. console.info(d.getSeconds()+""+d.getMilliseconds());  
  32. console.info("EndTest");  
  33. });  

ID测试耗时218毫秒,而CLASS测试耗时19.9秒!甚至在专门为该测试构建的简单页面上,ID搜索也要比CLASS搜索快100倍!

技巧#2-提供尽可能多的搜索信息

图6. 尽可能多地提供信息 
图6. 尽可能多地提供信息

jQuery提供如此多的页面元素搜索方法,有时您难以指出哪种方法是最好的。有一条经验是不会错的,即为搜索参数提供尽可能多的信息。因此,假如您正在搜索带有“clickable”CLASS的所有页面元素,如果您提前知道仅有DIV附带有CLASS,那么就能提高搜索性能。所以,搜索“div.clickable”会更加快。图6显示了支持该技巧的结果。

考虑到底层JavaScript代码之后,这就不足为奇了。通过提供元素标记,与CLASS参数匹配的搜索元素数量将大大减少,从而将搜索性能提升至与本例中的ID搜索相当。开发人员在编写jQuery选择方法时不能偷懒,尽管jQuery的简单让人产生偷懒的欲望。简单让您放松了警惕。搜索机制变得如此简单,让我们倾向于仅输入一条信息。然而,您应该总是尽可能多地输入信息,尤其是已知信息。清单2显示了一个很好的例子。

  1. //Assumethereare50oftheseinsomegiantform,andyouneedtovalidate  
  2. //thesefieldsbeforetheyaresubmitted,andtherearehundredsofother  
  3. //elementsonthepageaswell  
  4. <inputtypeinputtype=textclass="notBlank"> 
  5.  
  6. //the"bad"waytovalidatethesefields  
  7. $(".notBlank").each(function(){  
  8. if($(this).val()=="")  
  9. $(this).addClass("error");  
  10. });  
  11.  
  12. //the"good"waytovalidatethesefields  
  13. $("input.notBlank").each(function(){  
  14. if($(this).val()=="")  
  15. $(this).addClass("error");  
  16. });  
  17.  
  18. //the"best"waytovalidatethesefields  
  19. $("input:text.notBlank").each(function(){  
  20. if($(this).val()=="")  
  21. $(this).addClass("error");  
  22. });  

技巧#3-缓存选择器

最后一个性能技巧利用了几乎所有jQuery选择器都返回jQuery对象这个特性。这意味着在理想的情况下,您仅需要运行选择器一次,并且能够轻松地将所有函数连接在一起,或缓存结果供以后使用。您也不要担心缓存,因为与总体可用内存相比,返回的对象是很小的。清单3给出了一些关于如何利用缓存的例子。

  1. //Imagineafunctionthathidesallthediv'swithaclassof"hideable"  
  2. //whenabuttonispressed.TheseDIV'smightreappearlaterwhen  
  3. //workingwiththepage,sothebuttoncanbepressedanynumberof  
  4. //times,andtheDIV'sthathavereappeared  
  5. //willagainbemadetobehidden.  
  6.  
  7. $("#ourHideButton").click(function(){  
  8. $(".hideable").hide();  
  9. });  
  10.  
  11. //AsyousawintheCLASSversusIDexample,though,asearchfor  
  12. //CLASSisveryinefficient  
  13. //Ifthisbuttonispressedoften,itcouldleadtoaslowresponse  
  14. //Insteadoftheaboveexample,youshouldwriteyourcodelikethis  
  15.  
  16. varhideable;  
  17.  
  18. $("#ourHideButton").click(function(){  
  19. if(hideable)  
  20. hideable.hide();  
  21. else  
  22. hideable=$(".hideable").hide();  
  23. });  
  24.  
  25. //YoucancacheyoursearchinaJavaScriptvariableandreuseiteverytime  
  26. //thebuttonispressed.BecausejQueryalmostalwaysreturnsthe  
  27. //jQueryobject,youcansaveitthefirsttimeitiscalledforfutureuse  

在我的最后一个关于性能的示例代码中,将查看我在本系列的第一篇文章中提到的小部件(见参考资料)。这个小部件是在表的左上角上的复选框,它允许您选择或取消选择该列上的所有复选框。这个小部件在电子邮件应用程序中非常常见,用于选择或取消选择所有消息。

  1. //HereisthecodeasIoriginallypresenteditinthatarticle.Let'ssee  
  2. //ifwecanimprovetheperformanceinanywayfromthethingswelearnedhere  
  3.  
  4. functionselectAll()  
  5. {  
  6. varchecked=$("#selectall").attr("checked");  
  7. $(".selectable").each(function(){  
  8. varsubChecked=$(this).attr("checked");  
  9. if(subChecked!=checked)  
  10.  $(this).click();  
  11. });  
  12. }  
  13.  
  14. //Here'stheimprovedfunction.ThesearchfortheIDof"selectall"is  
  15. //OKas-is,becausewesawhowfasttheIDsearchis.  
  16. //ThesearchfortheCLASSof"selectable"wasnotwell-designedthough,  
  17. //becausewesawasearchbyCLASSisveryinefficient.  
  18. //Firststepwasimprovingthesearchbysupplyingasmuchinformationasweknow.  
  19. //WenarrowedthesearchtoonlycheckboxeswiththeCLASSofselectable.  
  20. //Thisshouldimproveoursearch  
  21. //Further,wecancachethissearchbecausewewillonlyneedtoperformitonce  
  22. //Finally,wecanperformthissearchbeforetheselectallcheckboxiseven  
  23. //checked(whenthepageisfinishedloading),sothatthesearchiscompleted  
  24. //andcachedbeforetheuserevenusesit.  
  25. //These3simpleperformancestepsgavemea200%increaseinspeedwhentested  
  26. //onapagewith200rowsofdata.  
  27.  
  28. varselectable=$(":checkbox.selectable");  
  29. functionselectAll()  
  30. {  
  31. varchecked=$("#selectall").attr("checked");  
  32. selectable.each(function(){  
  33. varsubChecked=$(this).attr("checked");  
  34. if(subChecked!=checked)  
  35.  $(this).click();  
  36. });  
  37. }  

关于性能的要点

使用JavaScript时,速度和性能绝对不是小问题。在现实中,创建jQuery的开发人员和处理浏览器内置JavaScript引擎的开发人员都非常关注性能问题。事实上,在最近6个月以来,浏览器开发的最重要问题就是JavaScript引擎的速度。浏览器开发者都致力于在下一年迅速提升JavaScript的执行性能,从而大大提高jQuery代码和JavaScript引擎的速度。来自这些“速度之战”的消息表明,提升JavaScript性能是大势所趋。

领导jQuery项目的JohnResig一直都在谈论他的最新“Sizzle”选择引擎。他从头编写了一个选择引擎,并声称初步结果表明它比Firefox要快4倍。这是巨大的速度提升!在我撰写本文的最后部分时,jQuery1.3已经发布,并且包含了Sizzle选择引擎。jQuery声称,在所有浏览器上运行的总体结果表明选择引擎的1.3版本比1.2.6版本的快49%。此外,1.3发布版在HTML注入(向DOM添加新的元素)上改进了6倍,在函数定位上改进了3倍。在我完成本文时,很多人都更新到了最新的jQuery发布版,这是非常令人激动的!

影响JavaScript性能的另一个因素是浏览器,如前所述,它的影响是所选的库的9倍。Firefox和Chrome在“最快JavaScript引擎”之战中各有胜负,而Safari的参与让竞争更加激烈。从我们上面的测试中,可以看到Chrome在JavaScript引擎性能方面远远超过Firefox,但是Firefox3.1将包含新的TracemonkeyJavaScript引擎,届时其速度将比当前的JavaScript引擎3.0快20至40倍(这是他们声称的,不是我的观点),真不可思议!在未来一两年内,您将看到底层JavaScript引擎和JavaScript库的速度得到巨大改进,从而导致使用JavaScript的Web应用程序将变得更加复杂。

如果您正在决定是使用JavaScript库还是自己编写JavaScript,那么需要考虑的另一件事情是处理和调试JavaScript库所需的全部工作。最近几年以来,有数百位用户一直在维护库中的每一个函数。您可能要忙到深夜,甚至筋疲力尽地编写自己的函数。

您更相信谁呢?另外,即使您能编写出比jQuery库更快的代码,您是否想过使用jQuery库能够获得更多的优势?您是否为了辛苦地编写自己的代码而放弃使用非常便利的jQuery及其函数库?自己编写代码不仅需要大量时间,并且还会产生更多bug,因此我还是建议使用现成的jQuery库。

我最后讨论的要点可能会让一些人沮丧,但是我们必须考虑编写这些jQuery库的程序员。他们当中的一些是最棒的,并且他们编写的超级优秀的代码(一般人不能编写这样出色的代码)都收入到这些库中。我承认自己远远不如编写jQuery库的程序员。因此,为何不利用他们的智慧?

结束语

本文从总体上讨论了jQuery和JavaScript库的性能。通过对选择方法进行大量的测试,您看到这些库之间的速度存在巨大的差距,并且jQuery是最快的库之一。不过,即使您选择了最快的JavaScript库,还是不能解决Web应用程序的性能问题,因为浏览器对性能的影响比库强9倍。如果您能够控制用户使用特定的Web浏览器,那么就让他们使用最快的浏览器。找到能够最快地运行您的Web应用程序的浏览器,并让用户通过使用它从中受益。理想情况下,让最慢的JavaScript浏览器消失意味着出现更快的Web应用程序。

最后,我们快速查看了jQuery和浏览器的JavaScript引擎即将推出的改进。在我撰写本文的结尾部分时,jQuery1.3已经发布了,它承诺在选择和代码的其他方面实现跳跃式性能改进。此外,Firefox还承诺它的下一代JavaScript引擎会快20至40倍!这些迹象表明,在未来的一两年内,JavaScript环境会在性能上取得重大突破。在不久的将来,复杂的Web应用程序会日益流行,因为快速运行这些程序的条件已经成熟。

【编辑推荐】

  1. jQuery高级应用:优化Web应用程序的最后绝招
  2. jQuery四大天王:核心函数详解
  3. jQuery中10个强大的遍历函数
  4. 即刻提升jQuery性能的十个技巧
  5. 一些应该熟记于心的jQuery函数和技巧
【责任编辑:王晓东 TEL:(010)68476606】

点赞 0
分享:
大家都在看
猜你喜欢

读 书 +更多

Absolute C++中文版(原书第2版)  

本书是讲解C++语言程序设计的优秀教程。全书围绕C++语言来组织,开始章节介绍编程的普通感念,接下来详细介绍C++中的继承、多态、异常处理...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊