# Производительность: бюджеты, память, CPU

Цель: виджет должен оставаться лёгким и не «съедать» ноутбук/телефон. Этот
документ фиксирует бюджеты, приёмы оптимизации и как измерять. Актуальные
цифры последнего прогона — `docs/perf-report.json` (генерируется
`npm run perf`).

## 1. Бюджеты (проверяются автоматически)

| Метрика | Бюджет | Почему |
|---|---|---|
| `packages/widget` JS (gzip) | ≤ 170 КБ | встраиваемый виджет, не должен заметно влиять на LCP чужой страницы |
| `packages/sdk` IIFE `agil-calls.js` (gzip) | ≤ 170 КБ | один скрипт = всё приложение |
| CSS виджета (raw) | ≤ 60 КБ | один файл, без UI-kit |
| JS heap после входа в звонок | ≤ 260 МБ | Chromium + fake video в headless; реальный ноут — меньше |
| FPS при звонке | ≥ 40 | видео должно идти плавно |
| Доля кадров >50 мс | ≤ 0.15 | отсутствие «залипаний» UI |
| Занятость main thread | ≤ 0.6 | запас на приложение компании |
| Адаптив 390/768/1366 | без horizontal overflow, контролы доступны | телефоны/ноуты |

`npm run perf` печатает таблицу и пишет `docs/perf-report.json`; при превышении
бюджета — код возврата 1 (gate в CI).

## 2. Что уже оптимизировано

**Размер бандла**
- Нет UI-фреймворка (vanilla + Web Components), нет иконочных шрифтов (inline SVG),
  один CSS-файл, темы — CSS-переменные.
- Медиа-модули грузятся динамически: MediaPipe (blur/liveness) — только при
  включении фичи, запись/STT — по действию пользователя.
- Протокол в бандле — только нужные функции (темы/качества/валидация конфига);
  zod-часть можно вынести (roadmap, −35–50 КБ gzip), т.к. сервер уже валидирует.

**Память**
- Один `AudioContext` на инстанс, `MediaStreamTrack.stop()` при leave, снятие
  `srcObject` у видео, `URL.revokeObjectURL` для записей/файлов.
- MediaPipe/сегментация выгружается при выключении blur (`close()` + null),
  canvas-буферы переиспользуются (пул), размер canvas ограничен (≤720p для
  обработки, независимо от входного потока).
- История чата на клиенте ограничена; заметки/анализ не аккумулируются в DOM —
  рендерится последняя порция.
- Скрытые вкладки: `document.visibilitychange` → пауза статистики/рендера,
  снижение частоты обновлений UI.

**CPU**
- `requestVideoFrameCallback`/rAF, без частых таймеров; статистика WebRTC — раз в
  2 с; DOM-обновления точечные (не перерисовываем сетку целиком).
- simulcast 3 слоя + `degradationPreference`, адаптивное понижение
  разрешения/битрейта (`evaluateQuality`), при плохом канале — video off +
  chat-fallback.
- Мобильный/слабый дефолт: 360p/15fps, ограничение числа плиток, пауза рендера
  невидимых (`IntersectionObserver`), `devicePixelRatio` cap.
- Запись (iframe/mixer) — только по требованию, canvas-микс с ограничением
  fps/разрешения.

**Рендер/вёрстка**
- CSS Grid + `container-type: inline-size`, никаких тяжёлых анимаций —
  `transform/opacity`, `prefers-reduced-motion`.
- Плитки: `<video>` без лишних слоёв, `object-fit: cover`, lazy `srcObject`.
- Никаких `backdrop-filter` поверх видео без необходимости (дорого на GPU) —
  только на контролах.

## 3. Измерение вручную

- `npm run perf` — автоматический бюджет-тест (артефакты + headless Chrome).
- Chrome DevTools: Performance (Main thread, Long tasks), Memory (heap snapshot
  до/после leave — не должно расти), `chrome://webrtc-internals` (bitrate,
  fps, frames dropped, jitter, RTT), Lighthouse на demo-странице.
- CPU throttling 4× в DevTools — проверка деградации и качества.
- Реальные устройства: iPhone SE/13, Android среднего класса, ноут с 2 ядрами;
  Safari/iOS — отдельная проверка WebRTC-политик.
- Нагрузка сервера: signaling лёгкий (сообщения), медиа — P2P; на 500 комнат
  важнее метрики WS/heartbeat, чем CPU медиа.

## 4. Известные ограничения MVP

- Mesh до 8 участников: каждый пир кодирует N−1 потоков → CPU растёт
  квадратично. Для больших встреч — SFU (LiveKit/mediasoup, roadmap), тогда
  клиент кодирует 1 поток.
- Браузерный blur (MediaPipe) — самый дорогой сценарий: включайте осознанно,
  на мобильных предлагайте отключить, используйте fallback CSS-blur.
- Headless-измерения пессимистичны по FPS/CPU (нет GPU-ускорения): реальные
  значения на устройствах обычно лучше; бюджеты выбраны с запасом.
- Память Chromium в headless с fake video выше, чем в реальном окне — бюджет
  heap 260 МБ соответствует худшему случаю 2 участников.

## 5. Чек-лист перед релизом

- [ ] `npm run perf` — все бюджеты соблюдены, `docs/perf-report.json` обновлён.
- [ ] `npm run build` — размеры бандлов не выросли >10 % без обоснования.
- [ ] Memory snapshot: после leave heap возвращается к уровню до звонка
  (±10 %), треки остановлены, MediaPipe закрыт.
- [ ] Мобильный профиль (390×844, CPU throttle 4×): FPS ≥ 24, controls
  доступны, нет overflow.
- [ ] Долгая сессия 30+ минут: нет утечек (heap стабилен), reconnect работает.
- [ ] При 8 участниках в mesh: видео ≤360p, качество деградирует, UI не
  блокируется (для продакшена с >8 — SFU).
