В первой статье цикла я уже рассматривал скорость работы движка, ответственного за создание и отображение HTML-страницы на экране. Однако, сейчас речь пойдет о несколько другом аспекте, нежели движок CSS-селекторов. Данная серия тестов была посвящена скорости создания отдельного HTML-документа.
Если в первых двух исследованиях ставилась под вопрос скорость распознавания браузером CSS-правил и их применение, то сейчас интересовал другой вопрос, а именно: как быстро браузер создает DOM-дерево в зависимости от наличия в нем элементов с id
или class
?
Для этого было подготовлено 3 набора HTML-файлов. Первый содержал 10000 элементов, у которых часть имеет id
(количество именованных элементов варьировалось от 50 до 10000). Во втором HTML-файлы были, практически, идентичными, только вместо id
имели атрибут class
. В третьем наборе в DOM-дереве были только элементы с id
(т.е. варьировалось само число элементов). Соответственно, все измерения проводились в скрытом iframe
, чтобы избежать отрисовки загружаемой страницы на экране.
Для замера времени создания страницы применялась та же, хорошо зарекомендовавшая себя, техника, что и в предыдущих тестах: бралась метка времени до набора элементов и после этого набора, затем из последней вычиталась первая. Итоговые результаты являются средневзвешенными по всем браузерам.
Дополнительно для тех HTML-файлов, которые содержали идентификаторы, запускалось вычисление getElementById('id1')
10000 раз (чтобы проверить, насколько количество элементов или идентификаторов влияет на эту процедуру). Результаты получились весьма интересные, хотя и очень предсказуемые. Наверное, в следующих исследования этот аспект работы браузеров будет исследован несколько подробнее.
Сами тесты можно погонять на webo.in/tests/css-efficiency-3/ или скачать на указанной странице все одним архивом (вместе с моими результатами).
Все 3 тестовых набора (каждый содержал по 6 файлов, в них было 50, 100, 500, 1000, 5000 и 10000 исследуемых элементов) прогонялся по 10 раз для 5 браузеров (Firefox2, IE6, IE7, Opera 9.5 (да-да, не стоит у меня 9.27) и Safari 3). В результате, статистическими методами погрешность сводилась ко вполне допустимому значению: 2–3%.
Сразу хочу оговориться о небольшом всплеске для самого первого документа у всех браузеров: скорее всего, при загрузке документа в iframe
браузер (это было характерно абсолютно для всех) выделяет определенное количество памяти для нового HTML-документа в этом iframe
, которое затем каким-либо образом повторно использует для новых документов. В результате для документа с 50 идентификаторами на 10000 элементов результаты оказались несколько неверными.
Наверное, в будущем этот аспект стоит учесть и загружать пустой документ в самом начале или, что лучше, загружать документ с максимальным количеством объектов, чтобы выделение памяти не влияло на дальнейшие измерения. Однако, на качественные выводы данное отклонение никак не повлияло.
Наверное, проще всего будет представить результаты в виде графиков, что я, в принципе и сделаю. Пару слов о легенде: на ней собрано 5 случаев. ID (create)
отражает время создания HTML-документа с 10000 элементов (div
), из которых только у 50...10000 были идентификаторы. class (create)
соответствует времени создания такого же документа, но с class
вместо id
. ID (clean)
характеризует время создания документа, в котором все элементы имели идентификаторы (но элементов всего было 50...10000). Два графика с 10000 get
показывают время на получения элемента с конкретным идентификатором 10000 раз в первом и третьем документе, соответственно.
Сами графики:
Рисунок 1. Скорость создания документа и выборки элемента для Firefox 2
Рисунок 2. Скорость создания документа и выборки элемента для IE 6
Рисунок 3. Скорость создания документа и выборки элемента для IE 7
Рисунок 4. Скорость создания документа и выборки элемента для Opera 9.5
Рисунок 5. Скорость создания документа и выборки элемента для Safari 3
Для Internet Explorer тяжело что-то понять, ибо время на вычисление элемента по идентификатору по порядку ненамного меньше времени создания документа, в итоге, оно «забивает» все результаты. Ниже приведены разделенные графики по средневзвешенному значению (естественно, основную роль играет Internet Explorer).
Рисунок 6. Скорость создания документа, средневзвешенно по всем браузерам
Рисунок 7. Скорость выборки элемента, средневзвешенно по всем браузерам
По графику средневзвешенных значений хорошо видно, что, при прочих равных условиях, создание документа с class
обходится меньшей кровью, чем с id
(в общем случае, от 2 до 10% выигрыша). Если принять во внимание, что element.class
-селекторы отрабатывают быстрее, чем #id
на те же 10%, то общий выигрыш при использовании в документе классов перед идентификаторами составит порядка 15%. В абсолютном значении эти цифры не так велики: для Centrino Duo 1.7 получается цифра примерно в 0,0085мс на 1 идентификатор (в среднем, 3 CSS-правила и 1 употребление).
Для документа со 100 элементами выигрыш может составить почти 1мс, для документа с 1000 — 8,5мс! Замечу, что средняя страница в интернете имеет 500–1000 элементов (проверить, сколько элементов на странице, можно просто запустив javascript:alert(document.getElementsByTagName('*').length)
в адресной строке браузера на какой-либо открытой странице), поэтому это уже то, за что можно побороться.
Однако (что и требовалось доказать, в общем), значительную нагрузку составляет именно создание DOM-дерева в документе (можно посмотреть, как экспоненциально растет время для Opera, Firefox и Safari) и самого документа (постоянное время в 60мс для IE, которое превосходит все остальные накладные расходы при создании среднего документа). В целом, эти операции уходит от 70% всего времени (т.е. наибольшая экономия достигается за счет минимизации размера дерева и количество HTML-страниц, загружаемых, например, во фрейме, в этой области планируется провести дополнительные исследования).
На скорость вычисления одного элемента по идентификатору, как ни странно, наибольшее влияние оказывает опять-таки DOM-Дерево, чем количество таких элементов. Даже при 1000 элементов с id
более половины временных издержек можно урезать, если просто сократить общее число элементов (особенно хорошо это заметно для IE).
В целом же, основных советов пока два: уменьшайте DOM-дерево и используйте id
только в случае действительной необходимости.