"Где еще живет скорость в web", Олег Елифантьев, MoscowJS 24

Post on 14-Aug-2015

138 views 0 download

Transcript of "Где еще живет скорость в web", Олег Елифантьев, MoscowJS 24

Где еще живет скорость в WebMoscowJS #24

Олег Елифантьев, @oelifantiev

Олег ЕлифантьевКомпания Тензор, г. Ярославль

Веб-разработчик (JavaScript, Node.JS)

Организатор Yaroslavl Frontend Meetup (http://yarfrontend.ru)

@oelifantiev

2

Давайте нарисуем снежинки?Менеджер: К новому году на сайт клиента нужны снежинки!

Dev: Okay boss!

3

Снежинка?• Простая текстовая нода

• position: absolute

• Анимируем через left, top

4

$('.snowflake').each(function(){

var pos = $(this).offset();

$(this).css({

top: pos.top + ...,

left: pos.left + ...

});

});

setTimeout(animate, 0);

5

Нужно больше

снежинок!

=(

Может быть проблема в JavaScript?

10

jQuery тормозит.

Расходимся.

=)

Анимировать будем так...function animate() {

var col = document.querySelectorAll('.snowflake');

for (var i = 0; i < col.length; i++) {

var rect = col[i].getBoundingClientRect();

col[i].style.top = ..., col[i].style.left = ...

}

setTimeout(animate, 0);

}

13

Что происходит?Как обычно, нам поможет DevTools

• Поймем что мерять

• Локализуем проблему

• Полечим

15

Будем мерять FPS

16

Маловато!• Приемлемо — хотя бы 30fps (33 ms/frame!)

• Идеально — 60fps (16.6 ms/frame!)

17

Почему так получилось?Запишем все происходящее

18

223 ms!

Style

recalculation

Style recalculation — вычисление стилей, применяемых к конкретному

элементу.

Это дешевая операция .

22

Layout

HTML�<body>

�<p>

�Длинный текст

�<img align="right" src="..."/>

�Еще текст

�</p>

�</body>

01.

02.

03.

04.

05.

06.

07.

24

HTML превращается в DOM-дерево

+ body

+-- p

+-- #text

+-- img

+-- #text

25

Есть еще "дерево рендеринга"Это длинный текст, который браузер

разобьет на прямоугольники (свой под

каждую строку) в зависимости от

размеров родительского блока, размера

шрифта, гарнитуры и даже этого кота.

Набор этих прямоугольников составит

"дерево рендеринга". Тут еще немного текста чтобы получилось

красиво…

26

Есть еще "дерево рендеринга"Это длинный текст, который браузер

разобьет на прямоугольники (свой под

каждую строку) в зависимости от

размеров родительского блока, размера

шрифта, гарнитуры и даже этого кота.

Набор этих прямоугольников составит

"дерево рендеринга". Тут еще немного текста чтобы получилось

красиво…

27

Layout — пересчет дерева рендеринга на основании стилей элементов

и других входных параметров, например размера окна браузера.

Это дорогая операция!

28

Что приводит к инвалидации дереварендеринга?

• Изменение определенных стилей элемента

• Размер, гарнитура шрифта

• Геометрия (width, height, margin, etc…)

• etc…

• Изменение DOM-дерева

29

Оптимизации…Браузер всячески старается оптимизировать процесс. Например, он

откладывает применение стилей и пересчет дерева рендеринга до

окончания синхронного блока JavaScript. Таким образом он

"пакетирует" несколько изменений в один расчет.

30

Ложка дегтяНо если в коде мы начинаем читать стилевую информацию, браузеру

приходится применить все отложенные расчеты здесь и сейчас для

того, чтобы ответить на наш запрос.

Это происходит синхронно. Все прочие процессы блокируются!

Эффект сравним с работой Garbage Сollector.

31

Что приводит к "чтению стилей"• getComputedStyle(elt)

• elt.style.???

• elt.getBoundingClientRect()

33

Вернемся к нашей анимацииvar col = document.querySelectorAll('.snowflake');

for (var i = 0; i < col.length; i++) {

// read one, forced layout

var rect = col[i].getBoundingClientRect();

// write one, layout invalidated

col[i].style.top = ..., col[i].style.left = ...

}

34

Как исправить?Все очень просто!

Нужно сначала все прочитать, а потом все записать!

Спасибо, Кэп!

35

function animate() {

var col = document.querySelectorAll('.snowflake');

[].slice.call(col)

// read all

.map(readCoordinates)

.map(applyAnimationStep)

// write all

.forEach(applyToDOM);

setTimeout(animate, 0);

}

36

Было

Стало

Paint

Еще раз посмотрим на Timeline

Включаем "Show paint rectangles"

44

Что делать? Заставим трудиться GPU!Вместо left и top для перемещения используем CSS Transforms

transform: translate3d(x, y, z);

46

Экономная

анимация

requestAnimationFrame!• Экономит CPU

• Делает анимацию более плавной

• Дает "привязку ко времени"

49

Используем знание о времени!function animate(ts) {

var col = document.querySelectorAll('.snowflake');

[].slice.call(col)

.map(calculateNextPosition(ts))

.forEach(applyToDOM);

requestAnimationFrame(animate);

}

50

will-change

CSS-свойство "will-change"Позволяет подсказать браузеру, что будет происходить с элементом.

Браузер может использовать для оптимизаций

.someElt { ... }

.someElt:hover { will-change: transform; }

.someElt:active { transform: rotate(90deg); }

52

will-change ?Опыт автора: Chrome 43 — эффект сомнительный.

53

Disclaimer :)Почти все это актуально не только для анимации! Любой код,

работающий с DOM, может выиграть!

• Сначала чтение, затем запись

• transform: translate3d

• requestAnimationFrame

• will-change

• И не забывайте про DevTools!

54

Спасибо за внимание!Доп. материалы: http://bit.ly/render-speed

Вопросы?

MoscowJS #24

Елифантьев Олег, Тензор

@oelifantiev

56