1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
---
title: Производительность анимации и частота кадров
slug: Web/Performance/Производительность_анимации
tags:
- CSS animation
- Developer Tools
- Web Performance
- Анимация
- Производительность
- инструменты
translation_of: Web/Performance/Animation_performance_and_frame_rate
---
<p>Анимация в Вебе может быть сделана с помощью {{domxref('SVGAnimationElement', 'SVG')}}, {{domxref('window.requestAnimationFrame','JavaScript')}}, включая {{htmlelement('canvas')}} и {{domxref('WebGL_API', 'WebGL')}}, CSS {{cssxref('animation')}}, {{htmlelement('video')}}, анимированных GIF и даже с помощью анимированных PNG и других типов изображений. Производительность CSS анимации может отличаться от одного CSS-свойства к другому, а попытка анимировать некоторые "дорогие" CSS-свойства может привести к зависаниям ({{glossary('jank')}}), даже несмотря на то, что браузер борется за то, чтобы смягчить частоту смены кадров {{glossary('frame rate')}}.</p>
<p>Для анимированных медиа, таких как видео и GIF, основная проблема производительности - это размер файлов. Скачивание больших по объему файлов не может не повлиять на производительность системы или на то, как эту систему воспринимает пользователь. </p>
<p>Анимации, основанные на коде, будь то CSS, SVG, <canvas>, webGL или другие JavaScript анимации, могут нести проблемы производительности сами в себе, даже если файлы этого кода скачиваются быстро. Такие анимации могут потреблять всё время CPU и приводить к зависаниям.</p>
<p>Несомненно, производительность каждой конкретной системы - очень чувствительная тема. Улучшив клиентскую производительность, вы сможете не только ускорить работу приложения, но даже затронете физический аспект - сможете сэкономить заряд батареи мобильных устройств и / или понизите температуру устройства. Поэтому очень важно владеть инструментами для измерения производительности. Они помогут вам понять всю работу, которую проводит браузер, пока рендерит ваше приложение и поможет избежать и диагностировать проблемы, когда они происходят.<br>
<br>
Пользователи ожидают, что взаимодействие с интерфейсом будет плавным, а интерфейс будет отзывчивым. Анимация помогает улучшить восприятие приложения, сделав его быстрым и отзывчивым; но анимация так же может замедлить его и привести к зависаниям, если она сделана неумело. Отзывчивые интерфейсы должны иметь частоту смены кадров, равную <a href="/en-US/docs/Tools/Performance/Frame_rate">60 кадров в секунду (fps)</a>. В то время, как не всегда возможно поддерживать такую частоту, очень важно поддерживать быструю и устойчивую смену кадров для анимации. </p>
<p>Мы рассмотрим, как можно использовать инструменты браузера для инспектирования частоты смены кадров. Так же, мы обсудим некоторые подсказки, как организовать и поддерживать быструю и стабильную смену кадров.</p>
<p>Графики <a href="/en-US/docs/Tools/Performance/Frame_rate">frame rate</a> и <a href="/en-US/docs/Tools/Performance/Waterfall">waterfall</a> из встроенных инструментов браузера дают информацию о том, как браузер выполняет работу по анимации. Используя эти инструменты, вы можете измерить fps приложения и диагностировать узкие места, в которых fps уменьшается.</p>
<p>С помощью <a href="/en-US/docs/Web/Guide/CSS/Using_CSS_animations">CSS анимации</a> вы указываете <a href="/en-US/docs/Web/CSS/@keyframes">ключевые кадры (keyframes)</a>, каждый из которых использует определенные CSS свойства, чтобы определить внешний вид элемента в конкретный (ключевой) момент анимации. Браузер создает анимации с помощью плавных переходов от одного ключевого кадра к следующему.</p>
<p>Если сравнивать анимацию с помощью JavaScript и CSS, вы увидите, что CSS-анимации проще создать. Более того, CSS-анимации гарантируют лучшую производительность, так как они автоматически делегируют некоторые задачи браузеру. Например, в случае CSS браузер сам решает, когда нужно отрендерить кадр, а когда пропустить кадр, если это необходимо. </p>
<p><br>
Однако, стоимость изменения разных CSS свойств варьируется. Общепринято, что 60 кадров в секунду - это достаточная частота, чтобы анимация выглядела мягкой и плавной. Несложный подсчет говорит, что при частоте 60 кадров в секунду, браузер имеет лишь 16.7 миллисекунд, чтобы выполнить все скрипты, пересчитать стили, скомпоновать слои и отрисовать новый кадр. Отсюда следует, что медленные скрипты и анимация дорогих CSS свойств может может привести к <a href="/en-US/docs/Glossary/Jank">зависаниям</a>, так как браузер все еще будет пытаться вычислить все 60 кадров.</p>
<p>Стоит заметить, что 60 кадров в секунду - это стандартная частота обновления экрана. Существуют экраны с гораздо большим FPS. Например, экраны игровых ноутбуков или iPad Pro 2018 имеют частоту смены кадров, равную 120 fps и выше. Для таких устройств производители браузеров ограничивают частоту 60-ю кадрами в секунду, но с помощю некоторых опций этот лимит можно убрать. И в этом случае, на формирование каждого кадра устройство будет отводить лишь 8.6 миллисекунд.</p>
<h2 id="Этапы_рендеринга">Этапы рендеринга</h2>
<p>Процесс, используемый браузером для отображения анимации CSS свойств, может быть представлен как последовательность этапов из следующего изображения:</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/10821/css-rendering-waterfall.png" style="display: block; height: 203px; margin-left: auto; margin-right: auto; width: 546px;"></p>
<ol>
<li><strong>Recalculate Style</strong>: когда любое CSS свойство для элемента изменяется, браузер должен заново вычислить результирующий набор свойств.</li>
<li><strong>Layout</strong>: затем браузер использует вычисленные стили для того, чтобы понять позицию и геометрию элементов - как измененного, так и рядом лежащих. Эта операция называется "layout", но иногда её так же называют "reflow".</li>
<li><strong>Paint</strong>: наконец, браузер должен перерисовать элементы на экране. Но этот этап не обязательно должен быть простым, как на изображении. Страница может быть разделена на слои, каждый из которых перерисовывается независимо, а только после этого они комбинируются в процессе, который называется композицией "Composition".</li>
</ol>
<p>Процессы, которые браузер использует для отрисовывания изменений на элементе <canvas> отличаются. В случае <canvas>, Layout не присходит. Скорее, страница будет перерисована с помощью JavaScript canvas API. </p>
<p>В любом случае, вычисление каждого следующего кадра должно происходить достаточно быстро, чтобы успеть попасть в частоту обновления экрана, чтобы не было зависаний.</p>
<h2 id="Стоимость_CSS_свойств">Стоимость CSS свойств</h2>
<p>На всех этапах рендеринга изменение некоторых свойств является более затратным, других - менее:</p>
<table class="fullwidth-table standard-table">
<thead>
<tr>
<th scope="col">Тип свойства</th>
<th scope="col">Стоимость</th>
<th scope="col">Примеры</th>
</tr>
</thead>
<tbody>
<tr>
<td>Свойства, затрагивающие геометрию или позицию элемента, запускают <strong>весь</strong> процесс заново: новое вычисление стилей, layout и перерисовку.</td>
<td><img alt="" src="https://mdn.mozillademos.org/files/10827/recalculate-style.png" style="height: 26px; width: 123px;"> <img alt="" src="https://mdn.mozillademos.org/files/10825/layout.png" style="height: 26px; width: 123px;"> <img alt="" src="https://mdn.mozillademos.org/files/10823/paint.png" style="height: 26px; width: 123px;"></td>
<td>
<p><code><a href="/en-US/docs/Web/CSS/left">left</a></code><br>
<code><a href="/en-US/docs/Web/CSS/max-width">max-width</a></code><br>
<code><a href="/en-US/docs/Web/CSS/border-width">border-width</a></code><br>
<code><a href="/en-US/docs/Web/CSS/margin-left">margin-left</a></code><br>
<code><a href="/en-US/docs/Web/CSS/font-size">font-size</a></code></p>
</td>
</tr>
<tr>
<td>
<p>Свойства, не затрагивающие геометрию и позиционирование элементов, но не лежащие в отдельном слое, запускают только вычисление стилей и перерисовку, но не Layout.</p>
</td>
<td><img alt="" src="https://mdn.mozillademos.org/files/10827/recalculate-style.png" style="height: 26px; width: 123px;"> <img alt="" src="https://mdn.mozillademos.org/files/10835/layout-faint.png" style="height: 52px; width: 123px;"> <img alt="" src="https://mdn.mozillademos.org/files/10823/paint.png" style="height: 26px; width: 123px;"></td>
<td>
<p><code><a href="/en-US/docs/Web/CSS/color">color</a></code></p>
</td>
</tr>
<tr>
<td>
<p>Свойства, которые рендерятся в отдельном слое не запускают даже repaint, так как результат обновления обрабатывается на этапе композиции.</p>
</td>
<td><img alt="" src="https://mdn.mozillademos.org/files/10827/recalculate-style.png" style="height: 26px; width: 123px;"> <img alt="" src="https://mdn.mozillademos.org/files/10835/layout-faint.png" style="height: 52px; width: 123px;"> <img alt="" src="https://mdn.mozillademos.org/files/10839/paint-faint.png" style="height: 26px; width: 123px;"></td>
<td><code><a href="/en-US/docs/Web/CSS/transform">transform</a></code><br>
<code><a href="/en-US/docs/Web/CSS/opacity">opacity</a></code></td>
</tr>
</tbody>
</table>
<div class="note">
<p>На Веб-сайте <a href="http://csstriggers.com/">CSS Triggers</a> хорошо показано, какие CSS свойства вызывают те или иные этапы обновления в разных браузерах.</p>
</div>
<h2 id="Пример_margin_против_transform">Пример: margin против transform</h2>
<p>В этом разделе мы увидим, как инструмент <a href="/en-US/docs/Tools/Performance/Waterfall">Waterfall</a> может указать на разницу между анимацией. ёё <code><a href="/en-US/docs/Web/CSS/margin">margin</a></code> и <code><a href="/en-US/docs/Web/CSS/transform">transform</a></code>.</p>
<p>Задумка этого сценария не в том, чтобы убедить вас, что анимация через <code>margin</code> - это всегда плохая идея. Сценарий нужен, чтобы продемонстрировать, как инструменты могут помочь вам понять работу браузера и как вы можете применить эти знания для оптимизации.</p>
<p>Если вы хотите самостоятельно разобраться с этим примером, вы можете найти демо <a href="http://mdn.github.io/performance-scenarios/animation-transform-margin/index.html">здесь</a>. Демо выглядит так:</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/11029/css-animations-demo.png" style="display: block; height: 677px; margin-left: auto; margin-right: auto; width: 1000px;">На экране всего два контрола: кнопка "start / stop" для запуска и остановки анимации и радио-кнопки для выбора свойства, с помощью которого происходит анимация: <code>margin</code>, или <code>transform</code>.</p>
<p>Так же на странице есть некоторое количество элементов со свойствами <code><a href="/en-US/docs/Web/CSS/linear-gradient">linear-gradient</a></code> и <code><a href="/en-US/docs/Web/CSS/box-shadow">box-shadow</a></code> Мы обращаем внимание именно на эти два свойства, так как они относительно дорогие.</p>
<p>Так же существует видео-версия анализа и оптимизации этой страницы.</p>
<p>{{EmbedYouTube("Tvu6_j8Qzfk")}}</p>
<h3 id="Анимация_свойства_margin">Анимация свойства margin</h3>
<p>Оставим включенной опцию "Use margin" и начнём анимацию. В это же время откроем "Performance tool" и нажмем кнопку "записать" (make a recording). Нам понадобится лишь пара секунд записи.</p>
<p>Откройте первую запись. Точное содержимое, которое вы увидите, зависит от вашего устройства, системной нагрузки и окружения, но, в целом это должно выглядеть так:</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/10853/margin-recording.png" style="display: block; height: 237px; margin-left: auto; margin-right: auto; width: 800px;"></p>
<p>На экране показаны три отдельных секции: (a) обзор этапов рендеринга (Waterfall), (b) частота кадров, и (c) детали на временной шкали.</p>
<h4 id="Обзор_этапов_рендеринга_на_временной_шкале_Waterfall">Обзор этапов рендеринга на временной шкале (Waterfall)</h4>
<p><img alt="" src="https://mdn.mozillademos.org/files/10857/margin-timeline-overview.png" style="display: block; height: 58px; margin-left: auto; margin-right: auto; width: 800px;"></p>
<p>Сейчас здесь показаны ужатые этапы рендеринга <a href="/en-US/docs/Tools/Performance/Waterfall">Waterfall</a>. Как видите, большая часть графика заполнена зеленым цветом - это говорит нам о том, что <a href="/en-US/docs/Tools/Performance/Timeline#timeline-color-coding">мы тратим много ресурсов на отрисовывание</a>.</p>
<h4 id="Частота_кадров_Frame_Rate">Частота кадров (Frame Rate)</h4>
<p><img alt="" src="https://mdn.mozillademos.org/files/10859/margin-frame-rate.png" style="display: block; height: 64px; margin-left: auto; margin-right: auto; width: 800px;"></p>
<p>Эта секция показывает <a href="/en-US/docs/Tools/Performance/Frame_rate">частоту кадров</a>. Средняя частота на примере - 46.67fps. Это ниже, чем желаемые 60fps. Однако, ещё хуже то, что частота кадров нестабильна - есть этапы, где частота кадров снижается до 20 и даже до 10 fps. Маловероятно, что вы увидите здесь плавную анимацию, особенно если добавите какое-то взаимодействие с пользователем.</p>
<h4 id="Этапы_рендеринга_в_деталях_Waterfall">Этапы рендеринга в деталях (Waterfall)</h4>
<p>Оставшаяся часть записей показа в секции "Waterfall view". Если вы пролистаете этот список, вы увидите что-то наподобие этого:</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/10861/margin-timeline.png" style="display: block; height: 532px; margin-left: auto; margin-right: auto; width: 800px;"></p>
<p>Это шаги рендеринга (<a href="/en-US/docs/Tools/Performance/Scenarios/Animating_CSS_properties#The_CSS_rendering_waterfall">rendering waterfall</a>). Для каждого кадра анимации мы вычисляем стили для каждого элемента, потом вычисляем Layout, а затем перерисовываем все элементы.</p>
<p>Из таблицы видно, что особый урон производительности наносит перерисовка Paint (зелёные полосы). Например, выделенный этап Paint занял 13.11мс. Учитывая, что весь бюджет рендеринга - 16.7мс, неудивительно, что мы увидели падения fps.</p>
<p>Вы можете поэкспериментировать с некоторыми свойствами. Например, попробуйте убрать box-shadow с помощью инспектора страницы (<a href="/en-US/docs/Tools/Page_Inspector/How_to/Examine_and_edit_CSS">Page / Element Inspector</a>), замерьте производительность и посмотрите, как это отразилось на производительности. Затраты на Paint уменьшатся значительно. Но они все ещё есть. Мы ещё вернёмся к этому вопросу позже, когда будем изучать использование <code><a href="/en-US/docs/Web/CSS/transform">transform</a></code> вместо <code><a href="/en-US/docs/Web/CSS/margin">margin</a></code>. Вы увидите, что от затрат на этот этап можно избавиться полностью.</p>
<h3 id="Анимация_свойства_transform">Анимация свойства transform</h3>
<p>Теперь, переключитесь на "Use transform" и запишите новые данные. Это должно выглядеть примерно так:</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/10863/transform-recording.png" style="display: block; height: 234px; margin-left: auto; margin-right: auto; width: 800px;"></p>
<h4 id="Обзор_этапов_рендеринга_на_временной_шкале_Waterfall_2">Обзор этапов рендеринга на временной шкале (Waterfall)</h4>
<p><img alt="" src="https://mdn.mozillademos.org/files/10869/transform-timeline-overview.png" style="display: block; height: 57px; margin-left: auto; margin-right: auto; width: 800px;"></p>
<p>В сравнении с <a href="/en-US/docs/Tools/Performance/Scenarios/Animating_CSS_properties#Waterfall_overview">версией, которая использует margin</a>, мы видим намного меньше зеленого, но намного больше фиолетового цвета. Это говорит о том, что вместо paint мы теперь тратим ресурсы на этапы <a href="/en-US/docs/Tools/Performance/Waterfall#timeline-color-coding">layout или style recalculation</a>.</p>
<h4 id="Частота_кадров_Frame_Rate_2">Частота кадров (Frame Rate)</h4>
<p><img alt="" src="https://mdn.mozillademos.org/files/10865/transform-frame-rate.png" style="display: block; height: 62px; margin-left: auto; margin-right: auto; width: 800px;"></p>
<p>В сравнении с <a href="/en-US/docs/Tools/Performance/Scenarios/Animating_CSS_properties#Frame_rate">версией, которая использует margin</a>, показатели fps здесь выглядят достаточно хорошо. Средняя частота кадров близка к 60fps, а стабильность fps, за исключением падения fps в начале значительно выросла.</p>
<h4 id="Этапы_рендеринга_в_деталях_Waterfall_2">Этапы рендеринга в деталях (Waterfall)</h4>
<p>В этой секции мы видим объяснения тому, что fps значительно улучшился. Мы больше не тратим время на layout и перерисовку элементов. :</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/10867/transform-timeline.png" style="display: block; height: 384px; margin-left: auto; margin-right: auto; width: 800px;"></p>
<p>Здесь, используя <code>transform</code>, мы заметно улучшили производительность приложения. А инструменты разработчика помогли нам это сделать.</p>
|