Содержание
На заметку: Это статья содержит числовые значения, зависящие от определённой сборки браузера. Со временем эти числа изменятся, как и представленные здесь данные.
Введение
Если вы из тех людей, кто интересуется тем, как работают браузеры, тогда вы уже наверняка прочли нескольких отличных статей, раскрывающих подробности рендеринга и сборки страниц Chrome с использованием графического ускорителя (GPU). Например, «Ускоренный рендеринг в Chrome: Многоуровневая модель» это отличное введением в то, как Chrome использует понятие слоя для отрисовки страниц. Для более глубокого понимания процесса вы можете прочесть статью «Ускорение сборки страницы в Chrome с использованием GPU», которая рассматривает то, как Chrome использует свои слои вместе с GPU для отрисовки страницы.
Краткий пересказ этих статей состоит в том, что с помощью аппаратного ускорения Chrome отрисует вашу страницу, растеризируя элементы страницы в прямоугольные области. Затем эти кусочки передаются графическому ускорителю, где аппаратная часть завершит их отрисовку на экране. Этот процесс называется сборкой (Compositing). Chrome будет перемещать области в память и из памяти, основываясь на необходимости и эвристиках исполнения, которые могут меняться в зависимости от платформы.
Философский вопрос
Я долго занимался написанием программных растеризаторов для работы с 3D, и для меня стало очевидным то, что производительность при отрисовке страницы будет меняться в зависимости от использованных CSS-свойств. Например, растеризация маленького изображения на экран происходит по совершенно другому алгоритму, чем отрисовка тени падающей на объект произвольной формы. Таким образом возникает вопрос: как различные CSS-свойства влияют на время отрисовки страницы?
Моей целью было классифицировать большой набор CSS-свойств и значений по времени их отрисовки, чтобы мы понимали, какие CSS-свойства лучше с точки зрения производительными. Чтобы этого добиться, я с помощью кувалды и такой-то матери соорудил систему для оценки времени отрисовки CSS. Система работает следующим образом:
- Генерируется набор независимых HTML-страниц, каждая из которых содержит единственный DOM-элемент и некоторое сочетание применённых к нему CSS-свойств.
- Запускается некоторый скрипт, проделывающий следующие действия для каждой
страницы:
- запустить Chrome.
- Загрузить страницу.
- Получить Skia Picture для страницы.
- Пропустить каждое полученное Skia Picture через Skia Benchmark для получения временных замеров.
- Вывести все замеры и полюбоваться на числа (это важно…)
Программный пакет растеризации Chrome называется SKIA, и он управляет не только растеризацией веб-страницы, но также и используется для удовлетворения всех нужд HTML5 Canvas API (блоки, линии, растровые заливки, тени, размытия, все вызовы Chrome для превращения DOM в пиксели). Чтобы облегчить отладку процесса отрисовки, SKIA позволяет сохранить в файлах Skia Picture (*.SKP) записи о всех командах, использованных при отрисовке страницы.
Используя этот пакет, мы генерируем набор HTML-страниц, в котором каждая страница содержит уникальную комбинацию CSS-свойств и их значений, например:
<style>
#example1 {
background: url(foo.png) top left / 50% 60%;
padding: 20px;
margin-top: 10px;
margin-right: 20px;
text-align: center;
}
</style>
<div id="example1">ВАУ</div>
И более сложный:
<style>
#example1 {
background-color:#eee;
box-shadow: 1px 2px 3px 4px black;
border-radius: 50%;
background: radial-gradient(circle closest-corner, white, black);
padding: 20px;
margin-top: 10px;
margin-right: 20px;
text-align: center;
}
</style>
<div id="example1">ВАУ</div>
Каждая страница затем загружается в новом экземпляре Chrome (чтобы быть уверенными в том, что временные замеры не были как-либо искажены устаревшими состояниями при перезагрузке страницы), затем создается Skia Picture (*.SKP) для определения списка Skia-команд, использованных для её отрисовки. Как только для каждой страницы сгенерируются SKP-файлы, мы запускаем другую серию операций и пропускаем файлы *.SKP через приложение Skia Benchmark (собранное из исходников Skia), которое выводит среднее время, требующееся для отрисовки конкретной страницы.
Оценка полученных данных
С этого момента у нас есть возможность составить грубую картину того, сколько времени требуется для отрисовки тех или иных наборов CSS-свойств. Мы даже можем начать упорядочивать CSS-свойства по производительности их отрисовки. Ниже приведен большой график, сделанный с помощью Chrome 27 beta и отображающий весь набор временных замеров из нашего процесса. Обратите внимание, что все эти данные могут меняться по мере того, как Chrome будет становиться быстрее и быстрее.
Каждая вертикальная черта представляет собой время отрисовки страницы с единственной комбинацией CSS-свойств (увеличено в 100 раз, истинный масштаб составляет всего [0, 1.56ms]). Здесь множество симпатичных линий, но в таком формате они в общем-то бесполезны. Нам нужно проанализировать данные, чтобы обнаружить в них закономерности.
Прежде всего мы находим подтверждение тому, что некоторые CSS-свойства попросту дороже остальных в плане отрисовки. Например, отрисовка тени для DOM-элемента включает в себя многопроходную операцию со сплайнами и другими богомерзкими штучками, в отличие от прозрачности, которую отрисовать легче.
Далее, интересно то, что, CSS-свойства могут иметь большее время отрисовки
в комбинации, нежели в сумме по отдельности. С точки зрения наблюдателя
это немного странно, мы обычно ожидаем, что A+B = C, а не 2,2C. В качестве
примера — добавление box-shadow
и border-radius-stroke
:
Что действительно интересно, так это то, что здесь уже не просто свойство
box-shadow
само по себе, а особое значение permutation.
Например, ниже показывается комбинация box-shadow: 50%
и border-radius
с
некоторыми разновидностями значений.
Для начала сойдет. Существует множество нетипичных комбинаций, которых мой тестовый набор не затрагивает. Впереди еще тысячи тестов и комбинаций, которые могут привести к интересным результатам.
Вычисление времени отрисовки страницы
Взяв на вооружение способность отслеживать время отрисовки каждого элемента на странице, у разработчиков появляется возможность оценки времени отрисовки и его влияния на отзывчивость вашего сайта. Несколько рекомендаций о том, с чего начать:
- Использует режим постоянной отрисовки в Chrome Dev Tools, чтобы определить дорогие с точки зрения производительности CSS-свойства.
- Включите разбор CSS в процесс анализа кода, чтобы обнаружить проблемы производительности. Найдите в CSS места, где вы используете дорогие с точки зрения производительности CSS-свойства, такие как градиенты и тени, и спросите себя, действительно ли они там нужны?
- Если сомневаетесь, всегда склоняйтесь в сторону решения, которое обеспечит улучшение производительности. Ваши пользователи могут не запомнить отступы у столбцов на вашей странице, но они точно запомнят ощущения от посещения вашего сайта.
К сожалению, на данный момент без ручной настройки описанного выше пакета не обойтись, сложно автоматизировать процесс вычисления времени отрисовки страницы, что в свою очередь усложняет создание непрерывного процесса кросс-платформенного тестирования.
Заключение
Наиболее интересно в этом эксперименте то, что временные замеры будут
продолжать изменяться с каждой новой версией Chrome (и, надеюсь,
отрисовка свойств ускорится). «Браузерное» ПО — это все время изменяющаяся
область. То, что медленно работает сегодня, может ускориться уже завтра. Из
этой статьи вы, конечно, можете вынести то, что нужно избегать указания
box-shadow: 1px 2px 3px 4px
для элемента, у которого уже есть
border-radius: 5
. Хотя если вы сделаете вывод, что CSS-свойства напрямую
влияют на время отрисовки вашей страницы, это принесет вам значительно больше
пользы.
Как и в случаях с любым ПО, удостоверьтесь в правильности ваших дизайнерских решений с точки зрения производительности и выбранной платформы что бы определить насколько они вам подходят.