После статьи «Разгоняем CSS-селекторы: стоит ли?» было предложено рассмотреть несколько дополнительных случаев, учитывающих транзитивность селекторов (например, насколько быстрее a c
, чем a b c
, или наоборот). Данное исследование посвящено как раз разбору таких случаев.
Методика и уменьшение погрешности подробно рассматривались в первой статье, на них сильно много останавливаться не буду. Скажу лишь, что при наращивании количества классов и идентификаторов Opera стала значительно медленнее (раза в 3) отображать код (при этом общий его объем увеличился примерно в 1,5-2 раза). Скорее всего, в следующую статью войдет исследование влияния количества классов/идентификаторов/размера кода на общую производительность браузера.
Еще раз подчеркну, что действительную ценность представляет относительное изменение времени отображения страницы в пределах одного браузера в зависимости от того или иного случая (а никак не абсолютное или же сравнение разных браузеров: дополнительно присутствует слишком много неучтенных факторов).
Для возможности работать с транзитивностью в (практически) полном объеме в исходную структуру документа были добавлены элементы третьего уровня (a
). В итоге, сам документ представлял большое линейное дерево, каждый из узлов которого являлся <div><p><a></a></p></div>
(с соответствующими классами или идентификаторами).
В первой группе предполагалось выяснить, насколько быстро работает транзитивность между тегами. Фактически, задача стояла в уточнении, что работает быстрее: выбор по названию класса или по тегу, а затем только, сузив область поиска, по названию класса. На это была нацелена первая группа:
a.class
p a.class
div a.class
div p a.class
Далее выяснялось, насколько в браузерах оптимизирована транзитивность по идентификаторам:
#id1
#id2 #id1
#id3 #id1
#id3 #id2 #id1
Затем смешанная транзитивность (по классам и по тегам):
p.class2 a.class1
div.class3 a.class1
div.class3 p.class2 a.class1
div.class3 p a.class1
Затем по идентификаторам и по тегам:
p a#id1
div a#id1
div p a#id1
div p#id2 a#id1
Загрузить все исходные файлы, равно как и пройти тест онлайн можно по адресу webo.in/tests/css-efficiency-2/.
Все числа как обычно сведены в одну большую таблицу. Выписано среднее время отображения страницы для различных вариаций селекторов и разных браузеров (внимание: тесты прогонялись локально, при онлайн тестировании замечены некоторые отклонения, но все тенденции сохраняются). Выделено время, меньшее по сравнению с аналогом.
Браузеры | Firefox 2.0 | Opera 9.5 | Safari 3 | IE 7 | IE 6 |
---|---|---|---|---|---|
a.class | 1617 | 9119 | 326 | 169 | 133 |
p a.class | 1697 | 9872 | 331 | 158 | 134 |
div a.class | 1661 | 10905 | 378 | 162 | 127 |
div p a.class | 1469 | 11667 | 344 | 169 | 127 |
#id1 | 1202 | 34200 | 335 | 164 | 123 |
#id2 #id1 | 1559 | 33235 | 320 | 169 | 130 |
#id3 #id1 | 1656 | 35355 | 324 | 169 | 133 |
#id3 #id2 #id1 | 1214 | 34608 | 397 | 175 | 137 |
p.class1 a | 2160 | 12675 | 342 | 150 | 108 |
div.class2 a | 2052 | 11971 | 369 | 153 | 108 |
div.class2 p.class1 a | 1511 | 12217 | 420 | 156 | 116 |
div.class2 p a | 1878 | 11871 | 366 | 150 | 110 |
p a#id1 | 1425 | 13163 | 359 | 166 | 122 |
div a#id1 | 1506 | 10572 | 341 | 156 | 116 |
div p a#id1 | 1474 | 12195 | 344 | 159 | 123 |
div p#id2 a#id1 | 1233 | 11916 | 353 | 169 | 133 |
Во-первых, сразу видно, что наследование селекторов по идентификаторам хорошо оптимизировано в браузерах (только не рекомендуется использовать более 2 подряд), средний выигрыш от использования 1 идентификатора вместо 2 или 3 невелик. Safari/Opera дали некоторый крен в сторону 2 идентификаторов, но, по моему мнению, это, скорее всего, связано с погрешностью эксперимента, ибо представить ситуацию, что две операции происходят быстрее, чем одна, достаточно тяжело.
Во-вторых, IE лучше себя ведет в наследовании классов/тегов: конструкции вида p.class2 a.class1
отрабатывают несколько быстрее, чем a.class1
. Подозреваю, что это связано с первоначальным сужением области перебора элементов. Когда мы выбираем один из узлов очень плоского дерева, то поиск внутри этого узла идет значительно быстрее, чем изначальный перебор всех возможных вариантов по дереву (в данном примере с помощью конструкции div
(#id
)). Средневзвешенный выигрыш: 9%.
Наследование тегов не дает никакого особого преимущества перед обычным использованием классов, но в некоторых случаях может оказаться быстрее (выигрыш в пределах погрешности). С наследованием идентификаторов и тегов ситуация очень похожа на наследование классов, наверное, браузеры также оптимизированы на разрешение ситуации, когда на странице используется несколько идентификаторов, поэтому сужение области перебора несколько ускоряет ситуацию.
Все остальные выводы можно сделать уже при более глубоком анализе. Возможно, также интересным будет сравнить производительность одной группы селекторов относительно другой.
Если у кого-то появятся идеи, как можно еще расширить имеющийся набор тестов, — стоит их обсудить. Спасибо за интерес к заметке.