2012-01-18 12 views
5

Mam framework, który generuje DOM aplikacji całkowicie przy użyciu document.createElement i document.appendChild. Teraz, gdy aplikacja staje się coraz większa, zauważyłem, że Chrome potrzebuje znacznie dłużej, aby zbudować DOM jako inne przeglądarki.Czy chromes "appendChild" jest naprawdę wolny?

Więc stworzyłem następujący test wydajności:

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); 

} 

Wyniki tego badania są bardzo ciekawe:

  • Chrome 16: 700+
  • Firefox 9: 560
  • IE 9: 210
  • Opera 11.60: 51

Chrome zajęło ponad 14 razy więcej czasu niż Opera. I to nie jest tylko bezsensowny punkt odniesienia! Naprawdę czuję tę różnicę w mojej aplikacji.

Czy to normalne, że Chrome działa tak wolno w operacjach DOM? Czy istnieje sposób na przyspieszenie?

Dzięki!

+3

'setTimeout' wydaje się prawdopodobne, aby zrzucić swój czas. – Domenic

+0

Możesz wstawić elementy div jednocześnie, a nie jeden po drugim. –

+2

@Domenic potrzebujesz setTimeout w tego rodzaju benchmarku, aby przeglądarka faktycznie działała zanim dostaniesz czas – Esailija

Odpowiedz

0

Myślę, że to normalne ....

To samo dotyczy manipulacji obiektami HTML (szerokość krycia & wysokość &), szczególnie jeśli używasz CSS3.

Zaprogramowałem pokaz slajdów (nie używając jQuery, nienawidzę go), który działa sprawnie ... w FF, IE, Opera, Safari, ... ale nie Chomre. W Chrome jest to niewiarygodnie powolne (tylko w nowszych wersjach Chrome, w starym jak wersja v12 było szybciej).

+0

To jest naprawdę smutne :( –

5

Aktualizacja 2

Oto hackish rodzaju rozwiązania, które mogą być warte trochę wykrywanie przeglądarki. Dzięki temu wydajność w moim testowaniu spadła do mniej niż 12,1 ////.

Możesz dodać kontener przed dodatkami, a następnie pokazać go ponownie. Możesz dostać trochę flasha, ale to chyba lepsze niż długie opóźnienie.

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); 
}; 

Jest to rodzaj wzrost wydajności że oczekiwałem od documentFragment.


Aktualizacja

Po uruchomieniu testu modified version z @Esailija's jsFiddle włączenie documentFragment, to nie wydaje się żadnej różnicy w Chrome (lub Opera dla tej sprawy), więc wygląda na to, że Chrome jest po prostu wolniejszy.


"Czy istnieje sposób, aby ją przyspieszyć?"

Zgaduję, że dostaniesz lepszą wydajność, jeśli używasz documentFragment, a następnie dołączyć do DOM z pojedynczym .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

Używanie documentFragment przyspieszyłoby to ogromnie, lub dowolny kontener, który nie jest jeszcze częścią DOM. robiąc to "za kulisami", co ich nie zawsze jest oczekiwanym zachowaniem. – jishi

+0

Twoja aktualizacja jest poprawna, używanie twojego kodu naprawdę nie przyspiesza. Jest różnica, ale tylko około 50ms ... Wciąż myślę, że powinno być na to rozwiązanie ...: S –

+0

@ VanCoding: Biorąc pod uwagę, że większość czasu pochodzi od przerysowywania strony, nie wiem, czy Naprawdę będziesz w stanie to zmienić. Jeśli masz nadzieję, że przeglądarka nie będzie wyglądać na zamrożoną, możesz podzielić to zadanie na mniejsze, asynchroniczne porcje, aby umożliwić użytkownikowi interakcję ze stroną. Poza tym nie wiem, co możesz zrobić, by poprawić odświeżanie Chrome. To całkiem dobrze pod maską. –

0

Twój test wydaje się być wadliwy. Jeśli do czystego appendChild test, Chrome wychodzi droga naprzód:

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

+4

testowanie tylko połączenia z appendChild to za mało! Prawdą jest, że samo wywołanie jest bardzo szybkie, ale po tym, jak JS przejdzie w stan spoczynku, chrom ma jeszcze wiele do zrobienia, zanim będzie mógł uruchomić Kolejny tick. We wszystkich innych przeglądarkach wygląda to inaczej, jednak: chciałem porównać cały proces, w tym cały czas przetwarzania. –

Powiązane problemy