Nos complace ver que la velocidad de algunas operaciones comunes del DOM aumentó vertiginosamente. Los cambios se realizaron a nivel de WebKit, lo que mejoró el rendimiento de Safari (JavaScriptCore) y Chrome (V8).
El ingeniero de Chrome Kentaro Hara realizó siete optimizaciones de código en WebKit. A continuación, se muestran los resultados que muestran cuánto más rápido se ha vuelto el acceso al DOM en JavaScript:
Resumen sobre el rendimiento del DOM
div.innerHTML
ydiv.outerHTML
el rendimiento mejoró 2.4 veces (V8, JavaScriptCore)- Rendimiento de
div.innerText
ydiv.outerText
en Chromium/Mac por 4x (V8/Mac) - Se mejoraron los accesos a las propiedades de CSS en un 35% (JavaScriptCore)
- El rendimiento de
div.classList
,div.dataset
ydiv.attributes
mejoró hasta 10.9 veces (V8). - El rendimiento de
div.firstElementChild
,lastElementChild
,previousElementSibling
ynextElementSibling
mejoró en 7.1 veces (V8). - Se mejoró el acceso a los atributos del DOM V8 entre un 4% y un 5% (V8).
A continuación, Kentaro Hara da detalles sobre algunos de los parches que hizo. Los vínculos son a errores de WebKit con casos de prueba, para que puedas realizar las pruebas tú mismo. Se realizaron cambios entre WebKit r109829 y r111133: Chrome 17 no los incluye, mientras que Chrome 19 sí.
Mejora 2.4 veces el rendimiento de div.innerHTML
y div.outerHTML
(V8, JavaScriptCore)
Comportamiento anterior en WebKit:
- Crea una cadena para cada etiqueta.
- Agrega una cadena creada a
Vector<string>
y analiza el árbol del DOM. - Después del análisis, asigna una string cuyo tamaño sea la suma de todas las strings en
Vector<string>
. - Concatena todas las strings en
Vector<string>
y muéstrala comoinnerHTML
.
Nuevo comportamiento en WebKit:
1. Asigna una cadena, por ejemplo, S.
1. Concatena una cadena para cada etiqueta en S y analiza el árbol del DOM de forma incremental.
1. Muestra S como innerHTML
.
En pocas palabras, en lugar de crear muchas cadenas y luego concatenarlas, el parche crea una cadena y, luego, las agrega de forma incremental.
Se mejoró el rendimiento de div.innerText
y div.outerText
en Chromium/Mac por 4x (V8/Mac)
El parche acaba de cambiar el tamaño del búfer inicial para crear innerText
. Cambiar el tamaño del búfer inicial de 2^16 a 2^15 mejoró el rendimiento de Chromium/Mac en 4 veces. Esta diferencia depende del sistema malloc subyacente.
Mejora en un 35%el rendimiento de los accesos a las propiedades de CSS en JavaScriptCore
Una cadena de propiedad de CSS (p.ej., .fontWeight
, .backgroundColor
) se convierte en un ID de número entero en WebKit. Esta conversión es pesada. El parche almacena en caché los resultados de la conversión en un mapa (es decir, una cadena de propiedad => un ID de número entero), para que la conversión no se realice varias veces.
¿Cómo funcionan las pruebas?
Miden el tiempo de los accesos a las propiedades. En el caso de innerHTML
(la prueba de rendimiento en bugs.webkit.org/show_bug.cgi?id=81214), la prueba solo mide el tiempo necesario para ejecutar el siguiente código:
for (var i = 0; i < 1000000; i++)
document.body.innerHTML;
La prueba de rendimiento usa un cuerpo grande copiado de la especificación HTML.
De manera similar, la prueba de accesos a la propiedad de CSS mide el tiempo del siguiente código:
var spanStyle = span.style;
for (var i = 0; i < 1000000; i++) {
spanStyle.invalidFontWeight;
spanStyle.invalidColor;
spanStyle.invalidBackgroundColor;
spanStyle.invalidDisplay;
}
La buena noticia es que Kentaro Hara considera que es posible realizar más mejoras en el rendimiento para otros atributos y métodos importantes del DOM.
¡Adelante!
Felicitaciones a Haraken y al resto del equipo.