Z radością obserwujemy, że niektóre z popularnych operacji DOM szybko rozwijają się w zawrotnym tempie. Zmiany zostały wprowadzone na poziomie WebKit, zwiększając wydajność zarówno przeglądarki Safari (JavaScriptCore), jak i Chrome (V8).
Kentaro Hara, inżynier Chrome, wprowadził siedem optymalizacji kodu w WebKit. Poniżej widać wyniki, które pokazują, o ile szybciej stał się dostęp do modelu DOM w języku JavaScript:
Podsumowanie wzrostu wydajności DOM
div.innerHTML
idiv.outerHTML
wydajność wzrosła 2,4 raza (V8, JavaScriptCore)- Wydajność
div.innerText
idiv.outerText
w Chromium/Macu 4x (V8/Mac) - Dostęp do właściwości CSS wzrósł o 35% (JavaScriptCore)
- Wydajność
div.classList
,div.dataset
idiv.attributes
wzrosła nawet o 10,9x (V8) - Wydajność
div.firstElementChild
,lastElementChild
,previousElementSibling
inextElementSibling
poprawiona o 7,1x (V8) - Dostęp do atrybutów DOM w wersji 8 poprawiono o 4–5% (wersja 8).
Poniżej Kentaro Hara podaje szczegółowe informacje na temat niektórych wykonanych przez siebie poprawek. Linki prowadzą do błędów w WebKit z przykładami testów, dzięki czemu możesz samodzielnie wypróbować testy. Zmiany zostały wprowadzone między WebKit r109829 a r111133: Chrome 17 ich nie zawiera, a Chrome 19 – nie.
Zwiększ wydajność div.innerHTML
i div.outerHTML
2,4 raza (V8, JavaScriptCore)
Poprzednie działanie w silniku WebKit:
- Utwórz ciąg znaków dla każdego tagu.
- Dołącz utworzony ciąg znaków do tabeli
Vector<string>
, aby przeanalizować drzewo DOM. - Po zakończeniu analizy przydziel ciąg znaków, którego rozmiar jest sumą wszystkich ciągów w elemencie
Vector<string>
. - Połącz wszystkie ciągi znaków w elemencie
Vector<string>
i zwróć go jakoinnerHTML
.
Nowy sposób działania w silniku WebKit:
1. Przydziel jeden ciąg znaków, powiedz S.
1. Połącz ciąg znaków dla każdego tagu z kodem S, stopniowo analizując drzewo DOM.
1. Zwróć S jako innerHTML
.
Krótko mówiąc, zamiast tworzyć wiele ciągów tekstowych i je łączyć, poprawka tworzy jeden ciąg, a następnie dołącza je stopniowo.
Zwiększ wydajność aplikacji div.innerText
i div.outerText
w Chromium/Macu 4x (V8/Mac)
Poprawka zmieniła początkowy rozmiar bufora przy tworzeniu pliku innerText
. Zmiana początkowego rozmiaru bufora z 2^16 na 2^15 poprawiła wydajność Chromium/Maca 4-krotnie. Różnica ta zależy od używanego systemu Mallok.
Zwiększ skuteczność dostępu do usług CSS w JavaScriptCore o 35%
Ciąg właściwości CSS (np. .fontWeight
, .backgroundColor
) jest w WebKit przekształcany w identyfikator liczby całkowitej. Ta konwersja jest bardzo duża. Poprawka zapisuje w pamięci podręcznej wyniki konwersji w postaci mapy (np. ciągu właściwości => identyfikatora całkowitej), dzięki czemu konwersja nie zostanie wykonana wielokrotnie.
Jak przebiegają testy?
Mierzą czas dostępu do usługi. W przypadku innerHTML
(test wydajności na stronie bugs.webkit.org/show_bug.cgi?id=81214) test mierzy tylko czas uruchomienia następującego 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 usługi porównywania cen mierzy czas wprowadzenia następującego kodu:
var spanStyle = span.style;
for (var i = 0; i < 1000000; i++) {
spanStyle.invalidFontWeight;
spanStyle.invalidColor;
spanStyle.invalidBackgroundColor;
spanStyle.invalidDisplay;
}
Kentaro Hara uważa, że w przypadku innych ważnych atrybutów i metod DOM możliwe będzie zwiększenie wydajności.
Dawaj!
Gratulacje dla Harakena i reszty zespołu.