2009-12-04 6 views
6

Podría alguien demostrarme que el consejo dado here (copiado abajo) con respecto a la eliminación de los elementos DOM antes de modificar y luego volver a la inserción de ellos es cada vez más rápido.el rendimiento de JavaScript - Dom Reflujo - Google artículo

Por probar, me gustaría ver algunas figuras. Es genial que investiguen esto, pero creo que el artículo es muy débil sin incluir detalles sobre cuál es realmente el 'problema' y cómo la solución lo soluciona en términos de velocidad (como el título del artículo Speeding up JavaScript)

The artículo ....

Out-of-the-flujo DOM Manipulación

Este modelo nos permite crear múltiples elementos e insertarlos en el DOM desencadenar una sola reflujo. Utiliza algo llamado DocumentFragment. Creamos un DocumentFragment fuera del DOM (por lo tanto, está fuera del flujo). Luego creamos y agregamos múltiples elementos a esto. Finalmente, movemos todos los elementos en DocumentFragment al DOM pero activamos un solo reflujo. El problema

Vamos a hacer una función que cambia el atributo className para todos los anclajes dentro de un elemento. Podríamos hacer esto simplemente iterando a través de cada ancla y actualizando sus atributos href. El problema es que esto puede causar un reflujo para cada ancla.

function updateAllAnchors(element, anchorClass) { 
    var anchors = element.getElementsByTagName('a'); 
    for (var i = 0, length = anchors.length; i < length; i ++) { 
    anchors[i].className = anchorClass; 
    } 
} 

La solución

Para resolver este problema, podemos eliminar el elemento del DOM, actualizar todos los anclajes, y luego insertar el elemento donde estaba. Para ayudar a lograr esto, podemos escribir una función reutilizable que no solo elimine un elemento del DOM, sino que también devuelva una función que insertará el elemento nuevamente en su posición original.

/** 
* Remove an element and provide a function that inserts it into its original position 
* @param element {Element} The element to be temporarily removed 
* @return {Function} A function that inserts the element into its original position 
**/ 
function removeToInsertLater(element) { 
    var parentNode = element.parentNode; 
    var nextSibling = element.nextSibling; 
    parentNode.removeChild(element); 
    return function() { 
    if (nextSibling) { 
     parentNode.insertBefore(element, nextSibling); 
    } else { 
     parentNode.appendChild(element); 
    } 
    }; 
} 

Ahora podemos utilizar esta función para actualizar las anclas dentro de un elemento que está fuera-de-la-flujo, y sólo desencadenar un reflujo cuando eliminamos el elemento y cuando insertamos el elemento.

function updateAllAnchors(element, anchorClass) { 
    var insertFunction = removeToInsertLater(element); 
    var anchors = element.getElementsByTagName('a'); 
    for (var i = 0, length = anchors.length; i < length; i ++) { 
    anchors[i].className = anchorClass; 
    } 
    insertFunction(); 
} 

Respuesta

5

Usted encontrará que es difícil conseguir cifras significativas para esto desde javascript perfilado como usted está realmente en el ahorro vuelve a pintar y que los fondos recuperados que no se mostrará en la mayoría de las herramientas de perfilado. Puede usar el Firebug paint events extension para mostrar visualmente la cantidad de repintes que está guardando.

+0

Niza extensión sin embargo, ambos ejemplos parecen hacer la misma cantidad de redibujados para mí. Cualquier posibilidad de que puedas dar una demostración en pastebin.me :) – redsquare

+0

Admitiré que la extensión ralentiza mucho las cosas, por lo que a veces puede ser difícil ver la diferencia en operaciones computacionalmente pesadas, p. Zoom de Google Maps. – Alex

1

La respuesta corta es que los cambios en el DOM de la página de disparo real Javascript eventos, evaluaciones CSS, la propagación de los cambios afecta a la interpretación del resto de la DOM alrededor de ella, etc. nodos desconectados en el flujo no tienen nada relacionado con eso, y las manipulaciones son mucho más económicas.

Una analogía: si fueras un animador trabajando en Toy Story 4, y en un render casi final viste un cambio que necesitas hacer en la física de la tela de una escena, ¿harías tus cambios mientras haces full- los detalles se renuevan para inspeccionar la escena, o se apagan las texturas y los colores, y se reduce la resolución mientras se realizan esos cambios.

+0

Quiero figuras. ¿Dónde están los beneficios? La teoría es genial. Al igual que Iraq tenía WOMD, mira lo que sucedió. Todavía no veo cómo hace que el js sea más rápido. Lo he perfilado y no puedo ver ningún beneficio. Solo me preguntaba qué me estaba perdiendo. – redsquare

+0

@redsquare: El título de ese artículo es engañoso y, de alguna manera, inexacto. No necesariamente hace que el JS sea más rápido ... hace que sea más rápido para el navegador representar el DOM. En otras palabras, el JS podría ejecutarse igual de rápido (o incluso más lento), pero la página aparecería más rápido, porque el navegador debe pasar menos tiempo refinando y volviendo a pintar. Reflejar y volver a pintar es la forma en que el navegador representa HTML y CSS. El rendimiento de JS no es lo mismo que el rendimiento de representación del navegador. Como ejemplo, las tablas son caras de renderizar, incluso cuando su sitio no tiene JS. – Pauan

+0

@redsquare: Creo que la razón por la que lo llamaron "acelerar JavaScript" es porque JS es * generalmente * lo que desencadena reflujos y repintados. En otras palabras, al cambiar su código JS, puede hacer que la página parezca más rápida. Pero no aparece más rápido porque el JS es más rápido, está apareciendo más rápido porque el navegador está reajustando y repintando menos. Por ejemplo, un applet de Java que manipule el DOM probablemente sea igual de malo, por lo que es inexacto llamarlo "velocidad de JavaScript". Realmente es velocidad de renderizado. – Pauan

2

pongo algunos enlaces en una página y probado el método en el artículo en comparación con la configuración del nombre de clase con los elementos que siguen en la página. He intentado esto en Firefox 3, Internet Explorer 8 y Chrome 3.

hice clases de los vínculos que tenían diferentes colores y diferentes tamaños de fuente.Como el texto del enlace tenía un tamaño diferente para las diferentes clases, estaba seguro de que la página tenía que volver a fluir.

Para cualquier número razonable de enlaces (hasta algunos miles), eliminar y agregar los elementos es un poco más lento.

Para una cantidad extremadamente grande de enlaces (10 000), eliminar y agregar elementos es un poco más rápido.

Sin embargo, la diferencia es bastante pequeña. Debes tener varios miles de enlaces para poder notar cualquier diferencia, y en 10 000 enlaces todavía hay algo así como una diferencia del 20%.

Por lo tanto, lo que he encontrado es que no puede esperar ningún cambio drástico de este método. Si tiene problemas de rendimiento, probablemente haya otros métodos que le den un resultado mucho mejor. Por ejemplo, intentaría cambiar el nombre de la clase del elemento padre en lugar de todos los elementos secundarios, y dejar que CSS haga el trabajo. Las pruebas que he hecho antes mostraron que esto puede ser unas diez veces más rápido.

0

No hay una manera confiable de saber cuándo ha finalizado un reflujo, aparte de mirar la página.

El tiempo dedicado calculando es prácticamente el mismo para agregar o cambiar elementos a la vez o uno por uno. La secuencia de comandos no espera al navegador entre los elementos, el navegador se pone al día.

A veces desea ver algo de inmediato, incluso si toma más tiempo procesarlo todo; otras veces desea esperar un poco más y mostrarlo todo cuando esté listo.

Si no puede decir cuál es mejor, haga que un diseñador mire las versiones una a una y todas a la vez, ¡pero no pregunte a dos diseñadores!

2

Esto es más o menos lo mismo que usar documentFragments para inicializar elementos en lugar de dom. Los fragmentos de documentos terminan siendo más rápidos porque tienen menos estructura y procesamiento real de los que preocuparse.

Estas son algunas de las notas de John Resig sobre las ventajas de rendimiento de fragmentos de documento (que están en uso en la actualidad jQuery):

http://ejohn.org/blog/dom-documentfragments/

Cuestiones relacionadas