Статьи Архив статей

Перевод: Мациевский Николай aka sunnybear
Опубликована: 16 марта 2009

На что влияет производительность CSS-селекторов

Примечание: ниже расположен перевод заметки Steve Souders "Performance Impact of CSS Selectors", в которой рассматривает насколько сильно набор CSS-селекторов влияет на производительность страницы. Дополнительные замечания Steve далее жирным, мои комментарии курсивом.

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

Первой мне на глаза попалась заметка CSS Qualified Selectors от Shaun Inman. В ней вообще-то речь не идет конкретно о CSS-производительности, но в одном из комментариев David Hyatt (архитектор Safari и движка WebKit, также участвовавший в проектах Mozilla, Camino и Firefox) разродился следующим:

Горькая правда относительно CSS3-селекторов заключается в том, что их вообще нельзя использовать, если вы заботитесь о быстродействии страницы. Используйте для оформления только классы и идентификаторы, и только их. Избегайте выбирать соседние элементы, наследники и дочерние узлы — они могут существенно снизить скорость отображения страницы во всех браузерах.

Тут стоит отметить, что речь не идет об использовании тегов вообще. Как показали тесты, лучше всего будет размечать страницу при помощи классов — их производительность до 20% выше.

Ух ты. И еще раз — ух ты.

А вот следующие заметки были совершенно потрясающими. Эта была серия тестов CSS-производительности от Jon Sykes в трех частях: часть 1, часть 2 и часть 3. Забавно наблюдать, как эволюционировали его тесты, поэтому по-настоящему стоит ознакомиться только с третьей частью. Это все заставило меня думать, что оптимизация CSS-селекторов является ключевым шагом в построении быстрых страниц.

Но была пара вещей, которые заставили меня задуматься. Во-первых, это большое число DOM-элементов и применяемых правил. На страницах было по 60000 DOM-элементов и 20000 CSS-правил (в аналогичных тестах я использовал наборы до 10 тысяч). По порядку эту значительно больше, чем встречается на рядовых страницах. Настолько большие страницы могут привести к совершенно непредсказуемому поведению браузеров (поэтому делать какие-то обоснованные выводы на таких объемах нельзя, и мы позже к этому вернемся). Ниже в таблице приведена статистика размера главной веб-страницы наиболее популярных в США вебсайтов.

ВебсайтЧисло DOM-элементовЧисло CSS-правил
Среднее1033923
AOL22891628
eBay305588
Facebook28821966
Google92552
Поиск Live376449
MSN1038886
MySpace932444
Wikipedia7951333
Yahoo!800564
YouTube821817

Во-вторых, меня поразил маленький размер базовой тестовой страницы по сравнению с более сложными вариантами. Основной вопрос, на который я хотел получить ответ, — это «действительно ли неэффективные CSS-селекторы тормозят загрузку страниц?» На всех пяти тестовых страницах было по 20000 ссылок (каждая из которых располагалась внутри P, DIV, DIV, DIV). CSS на странице последовательно проходит следующие стадии: базовую (никаких CSS-правил), селекторы для тега (одно правило для тега A), 20000 селекторов для классов, 20000 селекторов для дочерних узлов и наконец 20000 селекторов для прямых наследников в DOM-дереве (имеется в виду оператор >). Последние три страницы занимают более 3 Мб каждая. При этом базовая версия и только с селектором для тега, где почти (или совсем) нет CSS-правил, — всего лишь 1,8 Мб. В принципе, эти факты отвечают на вопрос: «насколько быстрой станет моя страница, если я уберу все CSS-правила?» Но ведь никто из нас не собирается этого делать, правда?

Я переделал эти тесты следующим образом:

  • 2000 ссылок и 2000 правил (вместо 20000) — это вылилось примерно в 6000 Элементов DOM из-за вложенности в P, DIV, DIV, DIV.
  • и базовая, и страница с селектором для тегов имели по 2000 правил — Также как и другие страницы, но эти были простые селекторы по классам, которые просто не соответствовали ни одному элементу на странице.

Я запустил эти тесты в 12 браузерах. Отображение страницы замерялось по скрипту, которые располагался вверху и внизу страницы (лично я считаю, что нужно было мерить window.onload: это будет более универсальной отметкой для всех браузеов). (Я загружал страницы прямо с локальной машины, чтобы избежать возможного эффекта дефрагментации пакетов при передаче данных.) Результаты приведены на диаграмме ниже. (Тут не показана Opera 9.63: она была очень медленной, все данные можно загрузить в csv-формате. Результаты можно также проверить прямо на тестовых страницах.)

Производительность меняется от браузера к браузеру: удивительно, но два самых новых браузера, IE 8 и Firefox 3.1, оказались самыми медленными — но просто сравнивать браузеры друг с другом здесь бессмысленно (хотя бы потому, что в движке WebKit совершенно отличная модель срабатывания событий готовности страницы или DOM-дерева). Хотя все тесты для заданного браузеры производились на одной и той же машине, разные браузеры могли тестироваться в различном окружении и на различном «железе». Целью всех этих экспериментов было не произвести сравнение браузеров по какому-то параметру, а только выяснить, насколько быстро они могут обрабатывать постепенно усложняющиеся CSS-селекторы.

[Замечание: при дальнейшем рассмотрении ситуации, сравнивая Firefox 3.0 и 3.1, я обнаружил, что для тестирования Firefox 3.1 и IE 8 я использовал более слабую машину, чем для других браузеров в этом эксперименте. Я дополнительно перезапустил тесты (в том числе и для Firefox 3.0 и IE 7) на той же слабой машине и обновил диаграмму выше. Даже после этих уточненных результатов не стоит использовать эти данные для сравнения производительности различных браузеров из-за возможных колебаний в тестовой окружении.]

Неудивительно, что более сложные страницы (с дочерними и последовательными селекторами) обычно проигрывают по скорости отображения. Самый большой неожиданностью оказалось то, что разница между производительностью базового случая и более сложными вариантами была крайне мала. Средний проигрыш по всем браузерам составил 50 мс, а если взять во внимание крупнейшие (IE 6&7, FF3), то и вовсе 20 мс. Для 70% и ли более текущих пользователей экстремальная оптимизация CSS-селекторов приведет к выигрышу, не превосходящему 20 мс.

Стоит иметь в виду, что все тестовые страницы являются, в среднем, самым плохим из текущих вариантов. 2000 ссылок, заключенных в P, DIV, DIV, DIV, занимали 6000 DOM-элементов, и это почти в два раза больше, чем самый большой сайт из первой десятки. И при этом на странице было 2000 крайне неэффективных селекторов — на обычном сайте примерно в три раза меньше правил, использующих наследственность или дочерние селекторы. Например, на Facebook при общем числе правил 2882 только 750 были таковыми.

Итак, почему мои результаты отличаются от упомянутых в самом начале заметки? Тут стоит отметить одно важное отличие: вещи становятся другими, если рассматривать их в большом масштабе. Все будет хорошо, если тестовые случаи по порядку совпадают с текущим положением вещей. Но в том случае, если браузеры видят страницу в 3 Мб с 60000 элементов и 20000 правил, все меняется. Я хочу особо отметить, что больше всего расходятся результаты для IE 6&7. Я так думаю, в этих браузерах есть какая-то заглушка при обработке CSS-селекторов. Чтобы найти ее более точно, я создавал тестовые страницы с наследственными и дочерними селекторами и последовательно увеличивал количество элементов и правил с 1000 до 20000. В результате я обнаружил характерный излом графика, который наступает для IE в районе 18000 правил. Но если IE 6&7 получают на вход страницу, примерно совпадающую по размеру с обычными (как в моих тестах), то они ведут себя гораздо более стабильно.

На основе всех этих тестов я могу сделать следующее заключение: для большинства вебсайтов возможный выигрыш от оптимизации CSS-правил не будет стоить затраченных на это усилий. Существует некоторый набор CSS-правил (тут Steve подразумевает, скорее всего, CSS3-правила) и JavaScript-методов (а тут конечно же работу с DOM), которые могут существенно замедлить страницу. И именно на этом стоит сфокусировать свои усилия. Поэтому я начну собирать реальные примеры небольших проблем, связанных с производительностью CSS-правил (offsetWidth, :hover), на которые стоит обращать свое внимание в первую очередь при анализе производительности страницы. Если у вас есть примеры, пожалуйста, поделитесь ими со мной (по поводу производительности offsetHeight уже есть отличная статья). Очень важно работать над той стороной производительности, которую наши пользователи в состоянии заметить.

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

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