2012-01-18 85 views
5

我有一個框架,完全使用document.createElementdocument.appendChild生成應用程序的DOM。現在應用程序變得越來越大,我注意到Chrome需要更長時間才能像其他瀏覽器一樣構建DOM。chromes「appendChild」真的那麼慢嗎?

所以,我創建了以下性能測試:

window.onload = function(){ 
    var now = new Date().getTime(); 
    for(var i = 0; i < 10000; i++){ 
     document.body.appendChild(document.createElement("div")); 
    } 
    setTimeout(function(){ 
     console.log(new Date().getTime() - now); 
    },0); 

} 

這個測試的結果很有意思:

  • 鉻16:700+
  • 火狐9:560
  • IE 9:210
  • Opera 11.60:51

Chrome比Opera完成了14倍多的時間完成。 這不僅僅是一個毫無意義的基準!我真的可以在我的應用中感受到這種差異。

Chrome在DOM操作上運行緩慢是否正常? 有沒有辦法加快速度?

謝謝!

+3

'setTimeout'似乎有可能甩開你的時間。 – Domenic 2012-01-18 16:13:12

+0

您可以一個接一個地插入div。 – 2012-01-18 16:14:55

+2

@Domenic你需要setTimeout這種基準,以便在你獲得時間之前,瀏覽器確實能夠正常工作 – Esailija 2012-01-18 16:15:21

回答

0

我覺得這很正常...。

對HTML對象操作(寬度&高度&不透明度)也是如此,特別是如果您使用CSS3。我編程了一個幻燈片(不使用jQuery,我討厭它),這是工作順利...在FF,IE瀏覽器,歌劇,Safari瀏覽器,...但不是Chomre。在Chrome中,它的速度令人難以置信(只有在較新版本的Chrome版本中,舊版本才更快)。

+0

真的很傷心:( – 2012-01-19 17:01:42

5

更新2

這裏有一個hackish的某種解決方案,這可能是值得一小的瀏覽器檢測。它將我測試中的性能降低到它不到的水平。

你可以在display='none'之前追加容器,然後再顯示它。你可能會有一點點閃光,但這可能比長時間的延遲要好。

window.onload = function(){ 

    var content = String.fromCharCode(Math.floor(Math.random() * 1000)); 

     // cache it in case it is already set 
    var disp = document.body.style.display; 

    document.body.style.display = 'none'; 

    var now = new Date().getTime(); 

    for(var i = 0; i < 10000; i++){ 
     document.body.appendChild(document.createElement("div")) 
      .appendChild(document.createTextNode(content)); 
    } 

    setTimeout(function(){ 
     console.log(new Date().getTime() - now); 
     document.body.style.display = disp || ''; // restore it 
    },0); 
}; 

這是那種我會從documentFragment預期的業績增長。


更新

運行modified version@Esailija's的jsfiddle測試包括的DocumentFragment後,它似乎並沒有把Chrome的差異(或者Opera爲此事)所以看起來好像Chrome只是慢一點。


「有沒有辦法來加快步伐?」

我猜,如果你使用一個documentFragment你會得到更好的性能,然後附加到DOM與單.appendChild

window.onload = function(){ 
    var now = new Date().getTime(); 

     // create a documentFragment 
    var frag = document.createDocumentFragment(); 

    for(var i = 0; i < 10000; i++){ 
     frag.appendChild(Div()); // append to the documentFragment 
    } 

     // append the documentFragment (which is emptied) 
    document.body.appendChild(frag); 

    setTimeout(function(){ 
     console.log(new Date().getTime() - now); 
    },0); 

    function Div(){ 
     var This = document.createElement("div"); 
     return This; 
    } 
} 
+2

使用documentFragment可以加快速度,或者任何尚未成爲DOM一部分的容器。做這個「幕後」,wh ich並不總是預期的行爲。 – jishi 2012-01-18 16:18:15

+0

你的更新是正確的,使用你的代碼並沒有真正加快速度。有一個區別,但只有大約50ms ...我仍然認爲應該有一個解決方案...:S – 2012-01-19 17:00:16

+0

@VanCoding:考慮到大部分時間來自頁面重繪,我不知道是否你真的可以改變這一點。如果您希望避免瀏覽器顯示爲凍結,您可以將任務分解爲較小的異步塊,以便用戶仍可以與該頁面交互。除此之外,我不知道你可以做些什麼來提高Chrome的重繪性能。這很好。 – 2012-01-19 17:16:45

0

您的測試出現瑕疵。如果你做一個純粹的appendChild測試中,Chrome的出來遙遙領先:

http://jsperf.com/appendchild-from-so

+4

基準只對appendChild的調用是不夠的!確實,調用本身非常快,但是在JS閒置之後,chrome在啓動之前還有很多事情要做在所有其他瀏覽器中,這似乎是不同的,但是:我想對整個過程進行基準測試,包括所有處理時間。 – 2012-01-19 17:12:03