2012-01-18 19 views
5

Tengo un marco que genera el DOM de una aplicación completamente usando document.createElement y document.appendChild. Ahora que la aplicación se hace cada vez más grande, noté que Chrome necesita mucho más tiempo para compilar el DOM que otros navegadores.¿Son los cromos "appendChild" realmente tan lentos?

tanto, he creado la siguiente prueba de rendimiento:

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

} 

Los resultados de esta prueba son muy interesantes:

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

Chrome tardó más de 14 veces más en completarse que Opera. ¡Y eso no es solo un punto de referencia sin sentido! Realmente puedo sentir esta diferencia en mi aplicación.

¿Es normal que Chrome sea tan lento en las operaciones de DOM? ¿Hay alguna manera de acelerarlo?

Gracias!

+3

'parece probable que deshacerse de su tiempo setTimeout'. – Domenic

+0

Puede insertar los divs de una vez, en lugar de uno por uno. –

+2

@Domenic necesita setTimeout en este tipo de punto de referencia para que el navegador realmente funcione antes de obtener el tiempo – Esailija

Respuesta

0

Creo que esto es normal ....

Lo mismo ocurre con la manipulación de objetos HTML (ancho & altura & opacidad), especialmente si utiliza CSS3.

Programé una presentación de diapositivas (no usando jQuery, lo odio) que funciona sin problemas ... en FF, IE, Opera, Safari, ... pero no en Chomre. En Chrome es increíblemente lento (solo en versiones de Chrome más nuevas, en versiones antiguas como v12 era más rápido).

+0

eso es realmente triste :( –

5

Actualización 2

Aquí es una especie hacker de solución, que puede valer la pena un poco de detección del navegador. Hace que el rendimiento en mis pruebas baje a menos de/de lo que era.

Puede display='none' el contenedor antes de agregarlo, luego muéstrelo de nuevo después. Puede obtener un poco de flash, pero eso es probablemente mejor que una larga demora.

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

Este es el tipo de aumento de rendimiento que yo habría esperado de la documentFragment.


actualización

Después de ejecutar una prueba de modified version@Esailija's jsFiddle para incluir el DocumentFragment, no parece hacer ninguna diferencia en Chrome (u Opera para el caso), por lo que parece que Chrome es simplemente más lento.


"¿Hay una manera de acelerarlo?"

que supongo que obtendrá un mejor rendimiento si se utiliza un documentFragment, y luego anexar al DOM con un solo .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

Usar un documentFragment lo aceleraría tremendamente, o cualquier contenedor que aún no formara parte del DOM. Supongo que Opera haciendo esto "detrás de escena", wh Ich no es siempre el comportamiento esperado. – jishi

+0

Su actualización es correcta, el uso de su código realmente no lo acelera. Hay una diferencia, pero solo unos 50ms ... Todavía creo que debería haber una solución para esto ...: S –

+0

@VanCoding: Teniendo en cuenta que la mayor parte del tiempo viene de la página redibujar, no sé si realmente podrás cambiar eso. Si espera evitar que el navegador aparezca congelado, puede dividir la tarea en fragmentos asincrónicos más pequeños para permitir que el usuario siga interactuando con la página. Aparte de eso, no sé qué podrías hacer para mejorar el rendimiento del redibujado de Chrome. Eso está bastante bien bajo el capó. –

0

Su prueba aparece dañada. Si lo hace una prueba pura appendChild, Chrome sale muy por delante:

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

+4

benchmarking solo la llamada de appendChild no es suficiente! Es cierto que la llamada en sí misma es muy rápida, pero después de que JS se queda inactivo, cromo todavía tiene mucho que hacer antes de que pueda iniciar el siguiente tick. En todos los otros navegadores, eso parece ser diferente. Sin embargo, quería comparar todo el proceso, incluido todo el tiempo de procesamiento. –

Cuestiones relacionadas