2011-07-25 23 views
40

El navegador web DOM ha existido desde finales de los años 90, pero sigue siendo una de las mayores limitaciones en rendimiento/velocidad.¿Pero por qué el DOM del navegador sigue tan lento después de 10 años de esfuerzo?

Tenemos algunas de las mentes más brillantes del mundo de Google, Mozilla, Microsoft, Opera, W3C y varias otras organizaciones que trabajan en tecnologías web para todos nosotros, así que obviamente no es un simple "Oh, no lo hicimos". 'optimizarlo'.

Mi pregunta es si tuviera que trabajar en la parte de un navegador web que trata específicamente con esto, ¿por qué me sería tan difícil hacerlo funcionar más rápido?

Mi pregunta no está pidiendowhat hace las cosas con calma, que está pidiendo why ha convertido no es más rápido?

Esto parece ir en contra de lo que sucede en otros lugares, como los motores JS con un rendimiento cercano al del código C++.

Ejemplo de escritura rápida:

for (var i=0;i<=10000;i++){ 
    someString = "foo"; 
} 

Ejemplo de lento debido a DOM:

for (var i=0;i<=10000;i++){ 
    element.innerHTML = "foo"; 
} 

Algunos detalles como por solicitud:

Después de banco de marca, parece que no es un problema lento sin solución, pero a menudo se usa la herramienta incorrecta, y la herramienta utilizada depende de lo que estés haciendo navegador cruzado

Parece que la eficiencia DOM varía mucho entre los navegadores, pero mi presunción original de que el dom es lento e irresoluble parece ser incorrecta.

me corrieron las pruebas contra Chrome, FF4, y el IE 5-9, se puede ver las operaciones por segundo en esta tabla:

enter image description here

Chrome es la velocidad del rayo cuando se utiliza la API de DOM, pero mucho más lento usando el operador .innerHTML (por una magnitud 1000 veces más lenta), sin embargo, FF es peor que Chrome en algunas áreas (por ejemplo, la prueba de anexión es mucho más lenta que Chrome), pero la prueba InnerHTML corre mucho más rápido que Chrome .

IE parece estar empeorando al usar DOM append y mejor en innerHTML a medida que avanzas en las versiones desde 5.5 (es decir, 73ops/seg en IE8 ahora a 51 ops/sec en IE9).

que tienen la página de prueba aquí:

http://jsperf.com/browser-dom-speed-tests2

Lo que es interesante es que parece diferentes navegadores parecen estar teniendo todas diferentes retos cuando se genera el DOM. ¿Por qué hay tanta disparidad aquí?

+0

Estoy comentando porque no sé, ** pero ** sospecho que es porque tiene que actualizarse cada vez que cambia algo. Lo mismo con TListView de Delphi: si agrega 1000 elementos en un bucle for ** sin ** llamar a 'Listview.BeginUpdate;' primero, será muy lento y consumirá mucha memoria. Sin embargo, si primero llama a BeginUpdate, no intenta volver a dibujar antes de llamar a endUpdate. – Jeff

+0

Por el amor de Dios respalde esto con algunos datos y puntos de referencia de las diferencias entre decir Firefox2 y Firefox8 y _muestre que el DOM es slow_ – Raynos

+1

Publicación relacionada de exGoogler sobre por qué el diseño DOM es tan anormalmente lento: https: // noticias. ycombinator.com/item?id=9155564. Publicación relacionada sobre aficionados: http://softwareengineering.stackexchange.com/q/191738/24257 – Pacerier

Respuesta

40

Cuando cambia algo en el DOM puede tener una miríada de efectos secundarios que hacer con el cálculo de los diseños, hojas de estilo, etc.

Esta no es la única razón: cuando configura element.innerHTML=x ya no se trata de las variables comunes "almacenar un valor aquí", sino con objetos especiales que actualizan una carga de estado interno en el navegador cuando los establece.

Las implicaciones completas de element.innerHTML=x son enormes. visión muy general:

  • de análisis x como HTML
  • piden extensiones del navegador de autorización
  • destruir nodos secundarios existentes de element
  • crear nodos hijos
  • estilos Recalcular que se definen en términos de padre-hijo relaciones
  • recalcula las dimensiones físicas de los elementos de página
  • notificar las extensiones del navegador de los cambios
  • actualización de las variables JavaScript que son identificadores de nodos DOM verdadera

Todas estas actualizaciones tienen que ir a través de una API que une el motor JavaScript y HTML. Una razón por la que Javascript es tan rápido en estos días es que lo compilamos con un lenguaje más rápido o incluso con un código de máquina, ocurren muchas optimizaciones porque el comportamiento de los valores está bien definido. Al trabajar a través de DOM API, no es posible ninguna de esto. Las aceleraciones en otros lugares han dejado atrás al DOM.

3

En primer lugar, cualquier cosa que haga al DOM podría ser un cambio visible para el usuario. Si cambia el DOM, el navegador tiene que volver a establecer todo. Podría ser más rápido, si el navegador almacena en caché los cambios, solo establece cada X ms (suponiendo que ya no lo haga), pero tal vez no exista una gran demanda de este tipo de características.

En segundo lugar, innerHTML no es una operación simple. Es un truco sucio que empujó MS, y otros navegadores adoptaron porque es muy útil; pero no es parte del estándar (IIRC). Usando innerHTML, el navegador tiene que analizar la cadena y convertirla en un DOM. El análisis es difícil.

3

El autor de la prueba original es Hixie (http://nontroppo.org/timer/Hixie_DOM.html).

Este problema se debatió en StackOverflow here y también. Con IE10, el problema está resuelto. Resuelto, quiero decir que se han movido parcialmente a otra forma de actualizar DOM.

El equipo IE parece manejar la actualización DOM similar al equipo Excel-macros en Microsoft, donde se considera una práctica deficiente actualizar las celdas activas en la hoja. Se supone que usted, el desarrollador, debe llevar a cabo la tarea de levantar objetos pesados ​​fuera de línea y luego actualizar el equipo en vivo por lotes. En IE se supone que debes hacer eso usando document-fragment (en lugar de documento). Con los nuevos estándares emergentes de ECMA y W3C, los fragmentos de documentos se deprecian. Entonces, el equipo de IE ha hecho un buen trabajo para contener el problema.

Les tomó algunas semanas desmontarlo de ~ 42,000 ms en IE10-ConsumerPreview a ~ 600 ms IE10-RTM. Pero les costó mucho esfuerzo sacarles la mano para convencerlos de que esto ES un problema. Su reclamo fue que no hay un ejemplo del mundo real que tenga 10,000 actualizaciones por elemento. Dado que el alcance y la naturaleza de las aplicaciones de Internet sofisticadas (RIA) no pueden predecirse, es vital tener un rendimiento cercano a los otros navegadores de la liga.Aquí es otra toma en DOM por OP en MS Connect (en los comentarios):

Cuando hojeo a http://nontroppo.org/timer/Hixie_DOM.html, se necesita ~ 680ms y si puedo guardar la página y ejecutarlo localmente, toma ~ 350 ms!

Lo mismo ocurre si utilizo el evento button-onclick para ejecutar el script (en lugar de body-onload). Comparar estas dos versiones:

jsfiddle.net/uAySs/ < - body onload

vs

jsfiddle.net/8Kagz/ < - botón onclick

diferencia Casi 2x ..

Aparentemente, el comportamiento subyacente de onload y onclick varía también. Puede ser aún mejor en futuras actualizaciones.

Cuestiones relacionadas