Мы очень рады видеть, что некоторые общие операции DOM резко возросли в скорости. Изменения были на уровне WebKit, повысив производительность как для Safari (JavaScriptCore), так и для Chrome (V8).
Инженер Chrome Кентаро Хара выполнил семь оптимизаций кода в WebKit; ниже приведены результаты, которые показывают, насколько быстрее стал доступ к JavaScript DOM:
Резюме повышения производительности DOM
- Производительность
div.innerHTML
иdiv.outerHTML
улучшена в 2,4 раза (V8, JavaScriptCore) - Производительность
div.innerText
иdiv.outerText
в Chromium/Mac выросла в 4 раза (V8/Mac) - Доступ к свойствам CSS улучшен на 35% (JavaScriptCore)
- Производительность
div.classList
,div.dataset
иdiv.attributes
улучшена до 10,9 раз (V8) - Производительность
div.firstElementChild
,lastElementChild
,previousElementSibling
иnextElementSibling
улучшена в 7,1 раза (V8) - Доступ к атрибутам DOM V8 улучшен на 4–5% (V8)
Ниже Кентаро Хара приводит подробности о некоторых из внесенных им исправлений. Ссылки ведут на ошибки WebKit с тестовыми случаями, так что вы можете попробовать тесты самостоятельно. Изменения были сделаны между WebKit r109829 и r111133: Chrome 17 не включает их; Chrome 19 включает.
Улучшение производительности div.innerHTML
и div.outerHTML
в 2,4 раза (V8, JavaScriptCore)
Предыдущее поведение в WebKit:
- Создайте строку для каждого тега.
- Добавляем созданную строку к
Vector<string>
, анализируя дерево DOM. - После анализа выделите строку, размер которой равен сумме всех строк в
Vector<string>
. - Объединить все строки в
Vector<string>
и вернуть его какinnerHTML
.
Новое поведение в WebKit: 1. Выделить одну строку, скажем S. 1. Объединить строку для каждого тега в S, постепенно анализируя дерево DOM. 1. Вернуть S как innerHTML
.
Короче говоря, вместо создания множества строк и их последующего объединения, патч создает одну строку, а затем просто добавляет строки пошагово.
Улучшение производительности div.innerText
и div.outerText
в Chromium/Mac в 4 раза (V8/Mac)
Патч просто изменил начальный размер буфера для создания innerText
. Изменение начального размера буфера с 2^16 на 2^15 улучшило производительность Chromium/Mac в 4 раза. Эта разница зависит от базовой системы malloc.
Повышение производительности доступа к свойствам CSS в JavaScriptCore на 35%
Строка свойства CSS (например, .fontWeight
, .backgroundColor
) преобразуется в целочисленный идентификатор в WebKit. Это преобразование является тяжелым. Патч кэширует результаты преобразования в карте (т. е. строка свойства => целочисленный идентификатор), так что преобразование не будет выполняться несколько раз.
Как работают тесты?
Они измеряют время доступа к свойствам. В случае innerHTML
(тест производительности в bugs.webkit.org/show_bug.cgi?id=81214 ) тест просто измеряет время выполнения следующего кода:
for (var i = 0; i < 1000000; i++)
document.body.innerHTML;
Тест производительности использует большой фрагмент, скопированный из спецификации HTML.
Аналогично тест доступа к свойствам CSS измеряет время выполнения следующего кода:
var spanStyle = span.style;
for (var i = 0; i < 1000000; i++) {
spanStyle.invalidFontWeight;
spanStyle.invalidColor;
spanStyle.invalidBackgroundColor;
spanStyle.invalidDisplay;
}
Хорошей новостью является то, что Кентаро Хара считает, что можно будет добиться большего повышения производительности для других важных атрибутов и методов DOM.
Давай!
Честь и хвала Харакену и остальной команде.