Пользователь мобильного приложения чувствует каждую задержку: долгий запуск, рывки при скролле, разряженную батарею. Вопросы о производительности задают на всех платформах, и ответ всегда начинается со слова «измерить».
Виды старта
- Холодный: процесса нет, система создаёт его, загружает код, инициализирует приложение и первый экран. Самый долгий.
- Тёплый: процесс есть или состояние частично сохранено, экран пересоздаётся.
- Горячий: всё в памяти, приложение выводится на передний план.
Android vitals считает чрезмерными холодный старт от 5 секунд, тёплый от 2, горячий от 1,5. Хорошая цель намного меньше: задержку замечают уже после секунды.
Как ускорить холодный старт
- Измерить на слабом устройстве и в поле (Android vitals, MetricKit).
- Убрать синхронную работу до первого кадра: инициализацию десятка SDK, миграции, чтение больших файлов, сетевые запросы.
- SDK инициализировать лениво или после первого кадра.
- Первый экран показать из кеша, свежие данные подтянуть фоном.
- Упростить иерархию первого экрана.
- Платформенное: Baseline Profiles на Android (заранее скомпилированный горячий код), меньше динамических библиотек на iOS.
- Закрепить метрикой в CI и алертами.
Главный поток
UI-фреймворки однопоточные: касания, раскладка и подготовка кадра идут на главном потоке. Бюджет кадра 16,7 мс на 60 Гц и 8,3 мс на 120 Гц. Всё, что не укладывается, даёт рывки. На Android блокировка около 5 секунд на событие ввода вызывает ANR, и доля ANR влияет на видимость в Google Play.
Списки
- Стабильные ключи элементов из данных, а не индексы.
- Никакой синхронной работы при привязке элемента: форматирование, парсинг, декодирование заранее.
- Картинки нужного размера, декодирование в фоне.
- Неизменяемые модели, чтобы декларативный UI не перерисовывал лишнее (стабильность параметров в Compose,
constи мемоизация во Flutter и React). - Точечные обновления вместо перестроения всего списка.
Память
У приложений жёсткие лимиты, а при нехватке система убивает процесс, часто без понятного крэша. Источники проблем: утечки экранов (LeakCanary, Memory Graph), полноразмерные картинки, неограниченные кеши.
Батарея и сеть
Радиомодуль после запроса остаётся активным ещё несколько секунд, поэтому много мелких запросов хуже пакетного. Точная геолокация держит GPS. Решения: группировать запросы, системные планировщики фоновой работы, push вместо опроса, значимые изменения местоположения.
Размер приложения
Android App Bundle и App Thinning отдают устройству только его ресурсы и архитектуру. Плюс R8, удаление неиспользуемых ресурсов и библиотек, сжатые форматы картинок, загрузка редкого по требованию. Размер влияет на конверсию установки.
Инструменты
| Платформа | Инструменты |
|---|---|
| Android | Android Studio Profiler, Perfetto, Macrobenchmark, JankStats, LeakCanary, Android vitals |
| iOS | Instruments (Time Profiler, Hitches, App Launch, Allocations), MetricKit, Organizer |
| Flutter | DevTools (Performance, Memory), профилирование в profile-режиме |
| React Native | профилировщик Hermes, React DevTools, нативные профайлеры |
Профилируют релизную (или profile) сборку на реальном устройстве.
Метрики
Время до первого кадра и до полезного контента, доля медленных кадров, ANR rate, crash-free users, потребление памяти, размер загрузки.
Что спросят на собесе
- Чем холодный старт отличается от горячего и как его ускорить?
- Почему тяжёлая работа на главном потоке приводит к рывкам и ANR?
- Как найти причину рывков в ленте?
- Как уменьшить размер приложения и расход батареи?
- Какими инструментами вы пользуетесь?