国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

記一次失敗的jQuery優化嘗試

開發 前端
這篇文章就記錄一次失敗的jQuery優化經歷。優化失敗這并不意味著jQuery的性能是優秀的,無法超越的,反之只能說它是一個相對封閉的庫,無法從外部介入進行優化。

我經常抱怨jQuery的DOM操作性能并不優秀,并且經常嘗試用一些方法去進行優化,但是越是優化,越是沮喪地發現jQuery其實已經做得很好,從使用者的角度能夠進行的優化實在有限(這并不意味著jQuery的性能是優秀的, 反之只能說它是一個相對封閉的庫,無法從外部介入進行優化)。這篇文章就記錄一次失敗的優化經歷。

優化思想

這一次優化的思想來自于數據庫。在數據庫優化的時候,我們常會說將大量的操作放在一個事務中一起提交,能有效提高效率。雖然對數據庫不了解的我并不知道其原因,但是事務的思想卻為我指明了方向(雖然是錯的)。

因此我嘗試將事務這一概念引入到jQuery中,通過打開和提交事務,從外部對jQuery進行一些優化,其最重要的在于減少each函數的循環次數。

眾所周知,jQuery的DOM操作,以get all, set first為標準,其中用于設置DOM屬性/樣式的操作,幾乎都是對選擇出來的元素的一次遍歷,jQuery.access函數就是其中最核心的部分,其中用于循環的代碼如下:

  1. // Setting one attribute  
  2. if ( value !== undefined ) {  
  3.     // Optionally, function values get executed if exec is true  
  4.     exec = !pass  exec  jQuery.isFunction(value);  
  5.  
  6. for ( var i = 0; i  length; i++ ) {  
  7. fn(  
  8. elems[i],  
  9. key,  
  10. exec ? value.call(elems[i], i, fn(elems[i], key)) : value,  
  11. pass  
  12. );  
  13. }  
  14. return elems; 

比如jQuery.fn.css函數就是這樣的:

  1. jQuery.fn.css = function( name, value ) {  
  2.     // Setting 'undefined' is a no-op  
  3.     if ( arguments.length === 2  value === undefined ) {  
  4.         return this;  
  5.     }  
  6.  
  7. return jQuery.access( this, name, value, truefunction( elem, name, value ) {  
  8. return value !== undefined ?  
  9. jQuery.style( elem, name, value ) :  
  10. jQuery.css( elem, name );  
  11. });  
  12. }; 

因此,下面這樣的代碼,假設被選擇的div元素有5000個,則要循環訪問10000個節點:

  1. jQuery('div').css('height', 300).css('width', 200); 

而在我的想法中,在一個事務中,可以如數據庫的操作一般,通過保存所有的操作,在提交事務的時候統一進行,將10000次節點訪問,減少至5000次,相當于提升了1倍的性能。

簡單實現

事務式的jQuery操作中,提供2個函數:

 ◆  begin:打開一個事務,返回一個事務的對象。該對象擁有jQuery的所有函數,但是調用函數并不會立刻生效,只有在提交事務后才會生效。

 ◆ commit:提交一個事務,保證所有事先調用過的函數都生效,交返回原本的jQuery對象。

實現起來也很方便:

 ◆ 創建一個事務對象,復制jQuery.fn上所有函數到該對象中。

 ◆ 當調用某個函數時,在預先準備好的隊列中添加調用的函數名和相關參數。

 ◆ 當提交事務時,對被選擇的元素進行一次遍歷,對遍歷中的每個節點應用隊列中的所有函數。

簡單地代碼如下:

  1. var slice = Array.prototype.slice;  
  2. jQuery.fn.begin = function() {  
  3.     var proxy = {  
  4.             _core: c,  
  5.             _queue: []  
  6.         },  
  7.         key,  
  8.         func;  
  9.     //復制jQuery.fn上的函數  
  10.     for (key in jQuery.fn) {  
  11.         func = jQuery.fn[key];  
  12.         if (typeof func == 'function') {  
  13.             //這里會因為for循環產生key始終是***一個循環值的問題  
  14.             //因此必須使用一個閉包保證key的有效性(LIFT效應)  
  15.             (function(key) {  
  16.                 proxy[key] = function() {  
  17.                     //將函數調用放到隊列中  
  18.                     this._queue.push([key, slice.call(arguments, 0)]);  
  19.                     return this;  
  20.                 };  
  21.             })(key);  
  22.         }  
  23.     }  
  24.     //避免commit函數也被攔截  
  25.     proxy.commit = jQuery.fn.commit;  
  26.     return proxy;  
  27. };  
  28.  
  29. jQuery.fn.commit = function() {  
  30. var core = this._core,  
  31. queue = this._queue;  
  32. //僅一個each循環  
  33. core.each(function() {  
  34. var i = 0,  
  35. item,  
  36. jq = jQuery(this);  
  37. //調用所有函數  
  38. for (; item = queue[i]; i++) {  
  39. jq[item[0]].apply(jq, item[1]);  
  40. }  
  41. });  
  42. return this.c;  
  43. }; 

測試環境

測試使用以下條件:

 ◆ 5000個div放在一個容器(div id="container"/div)中。

 ◆使用$(#containerdiv)選擇這5000個div。

 ◆每個div要求設置一個隨機背景色(randomColor函數),和800px以下的隨機寬度(randomWidth函數)。

參加測試的調用方法有3個:

 ◆正常使用法:

  1. $('#containerdiv')  
  2.     .css('background-color', randomColor)  
  3.     .css('width', randomWidth); 

 ◆單次循環法:

  1. $('#containerdiv').each(function() {  
  2.     $(this).css('background-color', randomColor).css('width', randomWidth);  
  3. }); 

 ◆事務法:

  1. $('#containerdiv')  
  2.     .begin()  
  3.         .css('background-color', randomColor)  
  4.         .css('width', randomWidth)  
  5.     .commit(); 

 ◆對象賦值法:

  1. $('#containerdiv').css({  
  2.     'background-color': randomColor,  
  3.     'width': randomWidth  
  4. }); 

測試瀏覽器選擇Chrome 8系列(用IE測就直接掛了)。

悲傷的結果

原本的預測結果是,單次循環法的效率遠高于正常使用法,同時事務法雖然比單次循環法慢一些,但應該比正常使用法更快,而對象賦值法其實是jQuery內部支持的單次循環法,效率應該是***的。

然而遺憾的是,結果如下:

正常使用法 單次循環法 事務法 對象賦值法
18435ms 18233ms 18918ms 17748ms

從結果上看,事務法成了最慢的一種方法。同時單次循環與正常使用并沒有明顯的優勢,甚至依賴jQuery內部實現的對象賦值法也沒有拉開很大的差距。

由于5000個元素的操作已經是非常龐大的循環,如此龐大的循環也沒能拉開性能的差距,平時最常用的10個左右的元素操作更不可能有明顯的優勢,甚至還可能將劣勢擴大化。

究其原因,由于本身單次循環法就沒有明顯的性能提升,因此依賴于單次循環,并是在單次循環之上進行外部構建的事務法,自然是在單次循環的基礎上還需要額外增加創建事務對象、保存函數隊列、遍歷函數隊列等開銷,結果敗給正常使用法也在情理之中。

至此,也算是可以宣布模仿事務的優化之道的失敗。但是對這個結果卻還能進一步地分析。

性能在哪里

首先,從代碼的使用上來分析,將正常使用法和測試中最快的對象賦值法進行比較,可以說兩者的差距僅在于循環的元素個數的不同(這里拋開了jQuery的內部問題,事實上jQuery.access的糟糕實現也確實有拖對象賦值法后腿之嫌,好在并不嚴重),正常使用法是10000個元素,對象賦值法是5000個元素。因此可以簡單地認為,18435 17748 = 687ms是循環5000個元素的耗時,這占到整個執行過程的3.5%左右,并不是整個執行過程的主干,其實真的沒有優化的必要。

那么另外96.5%的開銷去了哪里呢?謹記Doglas的一句話,事實上Javascript并不慢,慢的是DOM的操作。其實剩下96.5%的開銷中,除去函數調用等基本的消耗,至少有95%的時間是用在了DOM元素的樣式被改變后的重新渲染之上。

發現了這個事實之后,其實也就有了更正確的優化方向,也是前端性能中的基本原則之一:在修改大量子元素時,先將根父DOM節點移出DOM樹。因此如果使用以下的代碼再進行測試:

  1. //沒有重用$('#container')已經很糟糕了  
  2. $('#container').detach().find('div')  
  3.     .css('background-color', randomColor)  
  4.     .css('width', randomWidth);  
  5. $('#container').appendTo(document.body); 

測試結果始終停留在900ms左右,與前面的數據完全不在一個數量級之上,真正的優化成功。

教訓和總結

 ◆千萬要找到正確的性能瓶頸再進行優化,盲目的猜測只會導致走上錯誤而偏激的道路。

 ◆ 數據說話,數據面前誰也別說話!

 ◆不認為事務這個方向是錯誤的,如果jQuery原生就能支持事務這樣的概念,會不會有其他的點可以優化?比如一個事務自動會將父元素脫離出DOM樹之類的
 

原文鏈接:http://www.otakustay.com/a-failure-in-jquery-optimization/

【編輯推薦】

  1. jQuery 1.5正式版發布 五大變化引人注目
  2. 18個***最給力的jQuery教程分享
  3. 使用 jQuery 簡化 Ajax 開發
  4. jQuery實現表格數據的動態添加與統計
  5. jQuery1.5新特征之插件機制的救贖
責任編輯:陳貽新 來源: 張立理的博客
相關推薦

2021-01-08 13:52:15

Consul微服務服務注冊中心

2023-03-31 09:22:40

Hi3861芯片Flash

2020-02-10 10:15:31

技術研發指標

2019-09-11 08:22:57

MySQL數據庫遠程登錄

2021-11-11 16:14:04

Kubernetes

2020-08-10 11:00:02

Python優化代碼

2021-07-30 07:28:16

SQL優化日志

2021-10-14 10:53:20

數據庫查詢超時

2013-04-01 10:27:37

程序員失業

2021-12-20 10:15:16

zip密碼命令網絡安全

2019-03-15 16:20:45

MySQL死鎖排查命令

2023-06-07 07:31:04

PC端app脫殼技巧

2013-01-17 10:31:13

JavaScriptWeb開發firebug

2021-05-13 08:51:20

GC問題排查

2011-09-27 10:35:44

2022-03-02 09:01:07

CPU使用率優化

2022-01-07 11:48:59

RabbitMQGolang 項目

2014-08-11 09:31:52

2017-07-07 16:07:41

2023-04-06 07:53:56

Redis連接問題K8s
點贊
收藏

51CTO技術棧公眾號

成人日韩欧美| 日韩欧美二区三区| 国产黄色一级电影| 色综合天天综合狠狠| 色婷婷在线播放| 日韩中文字幕在线精品| 日韩成人久久| 国产女人18毛片水18精品| 亚洲免费影视| 3d动漫一区二区三区| 亚洲综合色区另类av| 调教一区二区| 国内成人精品一区| 国产欧美亚洲一区| 日韩欧美国产免费| 在线观看欧美日本| 国产成人久久精品一区二区三区| 成人国内精品久久久久一区| 久久成人免费日本黄色| 免费毛片aaaaaa| 日韩国产高清污视频在线观看| 国产96在线亚洲| 国产区一区二区| heyzo一本久久综合| 欧美3p视频在线观看| 亚洲人午夜精品免费| 99精品电影| 黄色成人在线看| 在线观看免费亚洲| 精品三级国产| 蜜桃久久精品乱码一区二区 | 日韩欧美精品免费在线| 涩涩网在线视频| 91精品综合视频| 91女人视频在线观看| 337p日本欧洲亚洲大胆鲁鲁| 久久99热精品| 丝袜诱惑亚洲看片| 国外男同性恋在线看| 中文字幕日韩欧美在线视频| 亚洲精品1区| 免费高清特黄a大片| 中文日韩电影网站| 视频一区视频二区中文| 在线视频观看你懂的| 九九精品视频在线观看| 欧美专区18| 一级毛片在线视频| 九九热最新视频//这里只有精品 | 一区二区三区视频国产日韩 | 欧美成a人免费观看久久| www.午夜色| 欧美三级电影在线观看| 日韩极品少妇| 蜜臀av午夜一区二区三区| 亚洲成年人影院在线| 亚洲天堂黄色| 啊灬啊灬啊灬啊灬高潮在线看| 久久影院资源网| 国产成人亚洲综合a∨猫咪| 动漫一区在线| 国产精品乱码视频| 天天综合色天天| 日韩美女毛片| 天天操天天摸天天爽| 中文字幕日韩精品有码视频| 久久精品国内一区二区三区| 免费毛片在线| 国产欧美精品xxxx另类| 亚洲三级理论片| 国内毛片久久| 欧美日韩中文在线视频| 在线精品91av| 成人一级视频在线观看| a欧美人片人妖| 国产精品12p| 国产视频亚洲精品| 国产一区二区三区久久久 | 欧美大片免费观看网址| 亚洲视频导航| 亚洲成人av资源网| 麻豆国产91在线播放| 欧美性猛片xxxxx免费中国| 好吊妞www.84com只有这里才有精品| 五月激情丁香一区二区三区| 国产一区网站| 亚洲人成小说| 亚洲综合色av| 欧美日韩国产高清一区二区| 国产一区二区三区四区三区四| 超碰97在线免费观看| 黑人巨大精品欧美一区二区小视频| 欧美影片第一页| 国产一区导航| av中文在线资源库| a级片一区二区| 色老头一区二区三区| 99精品视频中文字幕| 亚洲一区二区三区中文字幕在线观看| 色综合手机在线| 欧美一级高清免费播放| 性久久久久久久久| 精品二区视频| 国产无遮挡裸体视频在线观看| 特级黄色录像片| 日韩在线视频观看正片免费网站| 久久久久久久网| 国产精品欧美大片| 97在线资源| 国产伦精品一区二区| 欧美一区二区三区免费视频| 久久99精品国产麻豆不卡| 性感美女一区二区在线观看| 免费无码av片在线观看| 日本在线精品视频| 色婷婷精品久久二区二区蜜臀av| 久久aⅴ国产紧身牛仔裤| 丝袜美腿一区| 鲁一鲁一鲁一鲁一av| 91精品久久久久久久久久久久久久| 欧美色图一区二区三区| 久久99蜜桃精品| 日本超碰一区二区| 91青娱乐在线视频| 女女同性女同一区二区三区91| 一本色道久久综合狠狠躁篇怎么玩 | 国产精品久久久久久av公交车| 2020中文字字幕在线不卡| 3d蒂法精品啪啪一区二区免费| 91麻豆精品91久久久久同性| 国产精品一区在线观看你懂的| 国产日韩三级| 97超碰人人在线| 亚洲精品久久久久久久蜜桃臀| 日韩av三级在线观看| 欧美日韩国产bt| www.欧美色图| 欧美残忍xxxx极端| 久久青草伊人| 黄p免费网站| 日韩中文字幕一区| 韩国精品久久久999| 欧美日韩国产综合一区二区| 99精品欧美一区二区三区综合在线| 99久久综合| 成人免费一区| 全色精品综合影院| 成人网站免费观看入口| 成人网欧美在线视频| 国产亚洲精品久久久久久777| 亚洲一二三四久久| 国产精品资源网| 日韩在线中文| 成人免费在线观看视频| av小片在线| 成人淫片免费视频95视频| 五月天久久狠狠| 国产精品久久久久久av下载红粉 | 夜夜操天天操亚洲| 久久er精品视频| 欧美精品一区二区三区中文字幕| aa级大片免费在线观看| 快色在线观看| 女人帮男人橹视频播放| 亚洲综合自拍一区| 欧美激情视频免费观看| 欧美大胆人体bbbb| 亚洲国产aⅴ成人精品无吗| 国产在线不卡一区| 欧美在线1区| 91亚洲无吗| 亚洲女同志freevdieo| 欧美日韩伦理片| 91插插插插插插插插| 婷婷视频在线播放| 国产精品免费在线| 欧美资源在线观看| 日韩在线观看网址| 欧美mv日韩mv亚洲| 色婷婷综合中文久久一本| 26uuu国产电影一区二区| 日韩国产高清在线| 亚洲精品网址| 亚洲天堂日韩在线| 国产精品毛片无码| 中文在线а√在线8| 99热国产在线| 国产露出视频在线观看| 在线国产福利| 成人图片小说| 999在线免费视频| www成人免费| 亚洲精品8mav| 国产精品一区二区不卡视频| 欧洲永久精品大片ww免费漫画| 日韩三级影视基地| 亚洲视频专区在线| 日韩国产精品亚洲а∨天堂免| 欧美一区二区三区免费大片| 欧美视频中文字幕|