## Отслеживание проблем производительности web-приложений
Слайды доступны по ссылке
frontend.tech-mail.ru

##
Почему долго грузит? 😠

##
Почему, #$%@&, так лагает!!? 😡

# RAM

## Управление памятью в JavaScript

> JavaScript — это язык с автоматическим управлением памятью. В языке JavaScript память выделяется автоматически при создании объектов и освобождается тоже автоматически в процессе сборки мусора

## Когда может кончиться память?

- При создании очень большого количества объектов — например, при слишком агрессивном кешировании чего-нибудь, или вследствие плохого написания кода приложения
- При создании и работе с большими объектами — например, работа с медиафайлами (изображениями, видео)
- Вследствие утечек памяти

## Утечки памяти

> Утечка памяти — ситуация, когда память занимается объектами, которые больше не нужны приложению, но которые не могут быть освобождены автоматически из-за несовершенства алгоритмов сборки мусора

Чаще всего причиной утечек памяти являются т.н. нежелательные ссылки — ссылки, достижимые из корня, но ссылающиеся на фрагменты памяти, которые точно никогда больше не понадобятся

Например, потерявшие актуальность переменные, забытые в коде и удерживающие в памяти ненужные более объекты

## Случайные глобальные
переменные

    		// неявное объявление переменных
    		function foo(arg) {
    		    bar = 42; // будет создана глобальная переменная
    		}

    		foo();

## Случайные глобальные
переменные

    		// потеря контекста
    		const counter = {
    		    num: 0,
    		    inc() {
    		        this.num ++;
    		    },
    		}

    		setInterval(counter.inc, 1000); // ooops!

## Ссылки на удалённые DOM-узлы

    		// закэшировали ссылки
    		window.elements = {
    		    button: document.querySelector('button#inc'),
    		    cell: document.querySelector('.js-super-table td.js-super-cell'),
    		};

    		// do stuff

    		// элементы будут удалены из DOM, но останутся в памяти
    		document.removeChild(window.elements.button);
    		document.removeChild(document.querySelector('.js-super-table'));

## Утечки памяти, связанные с
замыканиями, колбеками

    		const trigger = document.getElementById('trigger');
    		const elementToRemove = document.getElementById('remove');

    		trigger.addEventListener('click', function () {
    		    document.removeChild(elementToRemove);
    		});

## Утечки памяти, связанные с
замыканиями, колбеками

    		// починить можно, например, так
    		const trigger = document.getElementById('trigger');
    		trigger.addEventListener('click', function () {
    		    const elementToRemove = document.getElementById('remove');
    		    document.removeChild(elementToRemove);
    		});

## Пример посложнее. Где здесь
утечка?

    		let state = { gen: 0 };
    		const updateState = function () {
    		    const oldState = state;
    		    state = {
    		        data: new Array(1024 * 1024).join('*'), // 2 MB of data
    		        gen: oldState.gen++,
    		    };
    		};

    		updateButton.onclick = updateState;

## Утечки памяти

    		let state = { gen: 0 };
    		const updateState = function () {
    		    const oldState = state;
    		    state = {
    		        data: new Array(1024 * 1024).join('*'), // 2 MB of data
    		        gen: oldState.gen++,
    		        log() { console.log(this.gen) }, // here!
    		    };
    		};

    		updateButton.onclick = updateState;

## Утечки памяти — пример

    		let state = { gen: 0 };
    		const updateState = function () {
    		    const oldState = state;
    		    const unused = function () {
    		        if (oldState) { console.log('hello here') }
    		    };
    		    state = {
    		        data: new Array(1024 * 1024).join('*'), // 2 MB of data
    		        gen: oldState.gen++,
    		        log() { console.log(this.gen) },
    		    };
    		};

## Инструменты разработчика для
поиска и отладки утечек памяти

- `window.performance.memory` — объект MemoryInfo
- Вкладка Performance
- Вкладка Memory Profiler
- Вкладка Performance monitor

Разберём, как ими пользоваться на примере

Ещё больше примеров по ссылке на developer.chrome.com

##
Производительность web-приложений

##
Как работают браузеры?

## Как работают браузеры?

> Frontend-разработчик, знакомый с внутренним механизмом работы браузеров, принимает более квалифицированные решения и понимает, почему следует выбрать те или иные средства

Кроме того, это просто интересно 😎

## Как работают браузеры?

1. Загрузка ресурсов страницы — тело документа, файлы скриптов и стилей
2. Парсинг HTML, построение DOM-дерева документа
3. Парсинг CSS, построение CSSOM
4. Выполнение JavaScript-кода
5. (re)calculating styles — рассчёт всех стилей, применяемых к элементам
6. layout (иначе, reflow) элементов страницы — рассчёт параметров элементов документа (ширина и высота элемента, его положение на странице)
7. (re)paint elements — рендер изображения элементов документа
8. compositing of layers — сведение всех слоёв в единое изображение в правильном порядке
9. `go to item four`

## Оптимизация работы браузеров

## Оптимизация JS

> Сегодня большинство устройств обновляют свои экраны 60 раз в секунду. Каждый из этих кадров может длиться чуть более 16 мс (1 секунда / 60 = 16,66 мс). В реальности же браузеру нужно выполнить и еще кое-какие действия, потому непрерывная работа JS должна занимать не более 10 мс

- Использование функции `requestAnimationFrame`
- Вынесение сложных вычисления, обработки больших объёмом данных в WebWorker'ы
- Асинхронная обработка данных по частям
- Оптимизация запуска тяжёлых функций с помощью Throttling и Debouncing
- Профилирование JS кода с помощью инструментов разработчика

## Throttling и Debouncing

> Throttling — декорирование функции при котором она будет выполняться не чаще одного раза в указанный период, даже если она будет вызвана много раз в течение этого периода. Т.е. все промежуточные вызовы будут игнорироваться

> Debouncing — декоратор позволяет превратить несколько вызовов функции в течение определенного времени в один вызов, причем задержка начинает заново отсчитываться с каждой новой попыткой вызова

## Оптимизации вычисления стилей

- Сокращение количества элементов в документе
- Сокращение сложности макетов
- Снижение сложности селекторов, уход от использования каскада стилей в сторону методологий, основанных на классах
- Профилирование и отладка с помощью инструментов разработчика

> Приблизительно 50 % времени, которое тратится на вычисление стиля элемента, уходит на сопоставление селекторов, а вторую половину времени занимает построение RenderStyle (представления стиля) на основе сопоставленных правил

## Оптимизации перерасчёта макета

- Избегание перерасчета макета, потому что зачастую, он выполняется для всего документа целиком
- Уменьшение количества элементов в документе
- Использование новых и более производительных способов вёрстки макета, например, использование flexbox-layout'ов вместо моделей макетов на основе float
- Избегание принудительных синхронных reflow всего документа — пример
- Профилирование и отладка с помощью инструментов разработчика

## Оптимизации перерисовок
элементов

- Изменение любого свойства, кроме transform и opacity, вызывает перерисовку
- Сокращение области прорисовки путем размещения элементов на отдельных слоях и оптимизации анимации
- Использование более простых css-свойств для стилизации элементов, избегание использования затратных css-свойств
- Профилирование и отладка с помощью инструментов разработчика

## Оптимизации компоновки слоёв

- Управление количеством слоёв
- Вынесение анимируемых элементов на новые слои с помощью свойств `will-change`, `transform`...
- Программирование анимаций с использованием правильных css-свойств: `transform`, `opacity`
- Профилирование и отладка с помощью инструментов разработчика

## Полезные ссылки

- Как работает с памятью JavaScript — статья на Хабре
- И ещё немного про утечки памяти
- Примеры утечек по ссылке на developer.chrome.com
- Небольшая статья на тему того, как работают браузеры: How Browsers Work: Behind the scenes of modern web browsers
- Очень подробно о всех аспектах производительности web-приложений: developers.google.com
- Ещё статьи про производительность: раз, два, три
- What forces layout / reflow

##
Перерыв

## Deploy
Что? Зачем? Куда?

## DNS

## Long time ago...

## Git way

## CI

## Автоматизировать всё!

## Управляем конфигурацией

## Docker way!

🚚 Каждый компонент системы в отдельном контейнере
⚒ Контейнеры содержат в себе всю конфигурацию
🌏 Образы хранятся в registry
🗓 Образы версионируются

## Всем спасибо!