Статьи

Автор: Николай Мациевский aka sunnybear
Опубликована: 18 марта 2008

Разгоняем CSS-селекторы. Часть 2: транзитивность

После статьи «Разгоняем CSS-селекторы: стоит ли?» было предложено рассмотреть несколько дополнительных случаев, учитывающих транзитивность селекторов (например, насколько быстрее a c, чем a b c, или наоборот). Данное исследование посвящено как раз разбору таких случаев.

Методика

Методика и уменьшение погрешности подробно рассматривались в первой статье, на них сильно много останавливаться не буду. Скажу лишь, что при наращивании количества классов и идентификаторов Opera стала значительно медленнее (раза в 3) отображать код (при этом общий его объем увеличился примерно в 1,5-2 раза). Скорее всего, в следующую статью войдет исследование влияния количества классов/идентификаторов/размера кода на общую производительность браузера.

Еще раз подчеркну, что действительную ценность представляет относительное изменение времени отображения страницы в пределах одного браузера в зависимости от того или иного случая (а никак не абсолютное или же сравнение разных браузеров: дополнительно присутствует слишком много неучтенных факторов).

Для возможности работать с транзитивностью в (практически) полном объеме в исходную структуру документа были добавлены элементы третьего уровня (a). В итоге, сам документ представлял большое линейное дерево, каждый из узлов которого являлся <div><p><a></a></p></div> (с соответствующими классами или идентификаторами).

Тестовые случаи

В первой группе предполагалось выяснить, насколько быстро работает транзитивность между тегами. Фактически, задача стояла в уточнении, что работает быстрее: выбор по названию класса или по тегу, а затем только, сузив область поиска, по названию класса. На это была нацелена первая группа:

  1. a.class
  2. p a.class
  3. div a.class
  4. div p a.class

Далее выяснялось, насколько в браузерах оптимизирована транзитивность по идентификаторам:

  1. #id1
  2. #id2 #id1
  3. #id3 #id1
  4. #id3 #id2 #id1

Затем смешанная транзитивность (по классам и по тегам):

  1. p.class2 a.class1
  2. div.class3 a.class1
  3. div.class3 p.class2 a.class1
  4. div.class3 p a.class1

Затем по идентификаторам и по тегам:

  1. p a#id1
  2. div a#id1
  3. div p a#id1
  4. div p#id2 a#id1

Загрузить все исходные файлы, равно как и пройти тест онлайн можно по адресу webo.in/tests/css-efficiency-2/.

Результаты

Все числа как обычно сведены в одну большую таблицу. Выписано среднее время отображения страницы для различных вариаций селекторов и разных браузеров (внимание: тесты прогонялись локально, при онлайн тестировании замечены некоторые отклонения, но все тенденции сохраняются). Выделено время, меньшее по сравнению с аналогом.

БраузерыFirefox 2.0Opera 9.5Safari 3IE 7IE 6
a.class16179119326169133
p a.class16979872331158134
div a.class166110905378162127
div p a.class146911667344169127
#id1120234200335164123
#id2 #id1155933235320169130
#id3 #id1165635355324169133
#id3 #id2 #id1121434608397175137
p.class1 a216012675342150108
div.class2 a205211971369153108
div.class2 p.class1 a151112217420156116
div.class2 p a187811871366150110
p a#id1142513163359166122
div a#id1150610572341156116
div p a#id1147412195344159123
div p#id2 a#id1123311916353169133

Выводы

Во-первых, сразу видно, что наследование селекторов по идентификаторам хорошо оптимизировано в браузерах (только не рекомендуется использовать более 2 подряд), средний выигрыш от использования 1 идентификатора вместо 2 или 3 невелик. Safari/Opera дали некоторый крен в сторону 2 идентификаторов, но, по моему мнению, это, скорее всего, связано с погрешностью эксперимента, ибо представить ситуацию, что две операции происходят быстрее, чем одна, достаточно тяжело.

Во-вторых, IE лучше себя ведет в наследовании классов/тегов: конструкции вида p.class2 a.class1 отрабатывают несколько быстрее, чем a.class1. Подозреваю, что это связано с первоначальным сужением области перебора элементов. Когда мы выбираем один из узлов очень плоского дерева, то поиск внутри этого узла идет значительно быстрее, чем изначальный перебор всех возможных вариантов по дереву (в данном примере с помощью конструкции div (#id)). Средневзвешенный выигрыш: 9%.

Наследование тегов не дает никакого особого преимущества перед обычным использованием классов, но в некоторых случаях может оказаться быстрее (выигрыш в пределах погрешности). С наследованием идентификаторов и тегов ситуация очень похожа на наследование классов, наверное, браузеры также оптимизированы на разрешение ситуации, когда на странице используется несколько идентификаторов, поэтому сужение области перебора несколько ускоряет ситуацию.

Все остальные выводы можно сделать уже при более глубоком анализе. Возможно, также интересным будет сравнить производительность одной группы селекторов относительно другой.

Если у кого-то появятся идеи, как можно еще расширить имеющийся набор тестов, — стоит их обсудить. Спасибо за интерес к заметке.

Читать дальше

Все комментарии (habrahabr.ru)