Siamo molto felici di vedere che alcune operazioni DOM comuni sono aumentate di velocità. Le modifiche sono state apportate a livello di WebKit, migliorando le prestazioni sia di Safari (JavaScriptCore) che di Chrome (V8).
L'ingegnere di Chrome Kentaro Hara ha apportato sette ottimizzazioni del codice in WebKit. Di seguito sono riportati i risultati, che mostrano quanto sia diventato più veloce l'accesso al DOM di JavaScript:
Riepilogo dei miglioramenti del rendimento del DOM
div.innerHTML
ediv.outerHTML
miglioramento delle prestazioni di 2,4 volte (V8, JavaScriptCore)- Aumento quadruplo (V8/Mac) delle prestazioni di
div.innerText
ediv.outerText
in Chromium/Mac - Accessi alle proprietà CSS migliorati del 35% (JavaScriptCore)
- Miglioramento delle prestazioni di
div.classList
,div.dataset
ediv.attributes
fino a 10,9 volte (V8) div.firstElementChild
,lastElementChild
,previousElementSibling
enextElementSibling
hanno registrato un miglioramento delle prestazioni di 7,1 volte (V8)- Accesso agli attributi DOM V8 migliorato del 4-5% (V8)
Di seguito, Kentaro Hara fornisce dettagli su alcune delle patch che ha creato. I link rimandano a bug di WebKit con casi di test, quindi puoi provare i test personalmente. Le modifiche sono state apportate tra WebKit r109829 e r111133: Chrome 17 non le include, mentre Chrome 19 sì.
Miglioramento delle prestazioni di div.innerHTML
e div.outerHTML
del 2,4 volte (V8, JavaScriptCore)
Comportamento precedente in WebKit:
- Crea una stringa per ogni tag.
- Aggiungere una stringa creata a
Vector<string>
, analizzando l'albero DOM. - Dopo l'analisi, alloca una stringa la cui dimensione è la somma di tutte le stringhe in
Vector<string>
. - Concatena tutte le stringhe in
Vector<string>
e restituiscile comeinnerHTML
.
Nuovo comportamento in WebKit:
1. Assegna una stringa, ad esempio S.
1. Concatena una stringa per ogni tag a S, analizzando in modo incrementale l'albero DOM.
1. Restituisce S come innerHTML
.
In breve, anziché creare molte stringhe e poi concatenarle, il patch crea una stringa e poi aggiunge semplicemente le stringhe in modo incrementale.
Miglioramento delle prestazioni di div.innerText
e div.outerText
in Chromium/Mac (V8/Mac) di quattro volte
Il patch ha appena modificato la dimensione del buffer iniziale per la creazione di innerText
. La modifica della dimensione del buffer iniziale da 2^16 a 2^15 ha migliorato le prestazioni di Chromium/Mac di quattro volte. Questa differenza dipende dal sistema malloc sottostante.
Miglioramento del 35%delle prestazioni degli accessi alle proprietà CSS in JavaScriptCore
Una stringa di proprietà CSS (ad es. .fontWeight
, .backgroundColor
) viene convertita in un ID intero in WebKit. Questa conversione è pesante. Il patch memorizza nella cache i risultati di conversione in una mappa (ad es. una stringa di proprietà => un ID intero), in modo che la conversione non venga eseguita più volte.
Come funzionano i test?
Misurano la data e l'ora degli accessi alla proprietà. Nel caso di innerHTML
(il test di prestazioni in bugs.webkit.org/show_bug.cgi?id=81214), il test misura solo il tempo di esecuzione del seguente codice:
for (var i = 0; i < 1000000; i++)
document.body.innerHTML;
Il test di rendimento utilizza un corpo di grandi dimensioni copiato dalla specifica HTML.
Analogamente, il test degli accessi alle proprietà CSS misura il tempo del seguente codice:
var spanStyle = span.style;
for (var i = 0; i < 1000000; i++) {
spanStyle.invalidFontWeight;
spanStyle.invalidColor;
spanStyle.invalidBackgroundColor;
spanStyle.invalidDisplay;
}
La buona notizia è che Kentaro Hara ritiene che saranno possibili ulteriori miglioramenti delle prestazioni per altri importanti attributi e metodi DOM.
Diamoci dentro!
Complimenti a Haraken e al resto del team.