Cieszymy się, że niektóre typowe operacje na DOM zostały znacznie przyspieszone. Zmiany zostały wprowadzone na poziomie WebKit, co zwiększyło wydajność zarówno Safari (JavaScriptCore), jak i Chrome (V8).
Inżynier Chrome Kentaro Hara wprowadził 7 optymalizacji kodu w WebKit. Poniżej znajdziesz wyniki, które pokazują, jak bardzo szybciej można teraz uzyskać dostęp do DOM w JavaScript:
Podsumowanie zwiększenia wydajności DOM
div.innerHTML
idiv.outerHTML
zwiększona wydajność o 2,4 raza (V8, JavaScriptCore)div.innerText
idiv.outerText
w Chromium/Mac o 4 razy (V8/Mac)- Dostęp do właściwości CSS szybszy o 35% (JavaScriptCore)
- Wydajność funkcji
div.classList
,div.dataset
idiv.attributes
wzrosła do 10,9 raza (V8). div.firstElementChild
,lastElementChild
,previousElementSibling
inextElementSibling
: wydajność poprawiona 7,1 raza (V8)- Dostęp do atrybutów DOM V8 poprawiony o 4–5% (V8)
Poniżej Kentaro Hara podaje szczegóły dotyczące niektórych wprowadzonych przez siebie poprawek. Linki prowadzą do błędów WebKit z przypadkami testowymi, dzięki czemu możesz samodzielnie przetestować te błędy. Zmiany zostały wprowadzone między wersjami WebKit r109829 a r111133: Chrome 17 ich nie zawiera, a Chrome 19 tak.
Zwiększenie wydajności funkcji div.innerHTML
i div.outerHTML
2,4 raza (V8, JavaScriptCore)
Wcześniejsze działanie w WebKit:
- Utwórz ciąg znaków dla każdego tagu.
- Dodaj utworzony ciąg znaków do
Vector<string>
, analizując drzewo DOM. - Po przeanalizowaniu przydziel ciąg znaków o długości równej sumie długości wszystkich ciągów w
Vector<string>
. - Połącz wszystkie ciągi znaków w parametry
Vector<string>
i zwróć je jakoinnerHTML
.
Nowe działanie w WebKit:
1. Przydziel jeden ciąg znaków, np. S.
1. Połącz ciąg znaków dla każdego tagu z S, stopniowo analizując drzewo DOM.
1. Zwraca S jako innerHTML
.
Krótko mówiąc, zamiast tworzyć wiele ciągów tekstowych i potem je łączyć, łatka tworzy jeden ciąg tekstowy, a potem po prostu dopisuje kolejne ciągi.
Zwiększenie wydajności funkcji div.innerText
i div.outerText
w Chromium/Mac 4-krotnie (V8/Mac)
Aktualizacja zmieniła początkowy rozmiar bufora podczas tworzenia innerText
. Zmiana początkowego rozmiaru bufora z 2^16 na 2^15 zwiększyła wydajność Chromium/Mac 4-krotnie. Ta różnica zależy od systemu malloc.
Wzrost o 35%wydajności dostępu do właściwości CSS w JavaScriptCore
W WebKit ciąg znaków właściwości CSS (np. .fontWeight
, .backgroundColor
) jest konwertowany na identyfikator całkowity. Ta konwersja jest ciężka. Aktualizacja w pamięci podręcznej przechowuje wyniki konwersji na mapie (czyli ciąg znaków usługi => identyfikator całkowity), aby konwersja nie była przeprowadzana wielokrotnie.
Jak działają testy?
Mają one na celu pomiar czasu dostępu do usługi. W przypadku innerHTML
(test wydajności w witrynie bugs.webkit.org/show_bug.cgi?id=81214) testuje się tylko czas wykonywania tego kodu:
for (var i = 0; i < 1000000; i++)
document.body.innerHTML;
Test wydajności używa dużej treści skopiowanej ze specyfikacji HTML.
Podobnie test dostępu do właściwości CSS mierzy czas wykonywania tego kodu:
var spanStyle = span.style;
for (var i = 0; i < 1000000; i++) {
spanStyle.invalidFontWeight;
spanStyle.invalidColor;
spanStyle.invalidBackgroundColor;
spanStyle.invalidDisplay;
}
Dobrą wiadomością jest to, że według Kentaro Hara możliwe będzie wprowadzenie dalszych ulepszeń wydajności w przypadku innych ważnych atrybutów i metod DOM.
Dawaj!
Gratulacje dla Harakena i reszty zespołu.