Отслеживание проблем производительности web-приложений, инфраструктура и деплой web-приложений, практики DevOps

Технопарк, весна, 2024 г.

Отслеживание проблем производительности 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) },
		    };
		};
		 
	

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

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

Ещё больше примеров по ссылке на 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 мс

Throttling и Debouncing

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

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

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

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

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

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

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

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

Перерыв

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

DNS

Long time ago...

Git way

CI

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

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

Docker way!

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

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