Размер приложения и холодный старт — бюджет производительности
150 МБ APK и 4 секунды до первого экрана — это не «вырасли с фичами», это потеря 20-30% юзеров на первой установке. Разбираем, какой бюджет реально держать, что грузит размер сильнее всего и где экономить на старте.
Каждые 6 МБ установочного размера приложения — это минус 1% к конверсии установки (данные Google 2025). Каждая секунда холодного старта свыше 2 — минус 5-10% к удержанию в первую неделю. Эти цифры не пугают команды, пока не посмотришь на свои.
Целевой бюджет на 2026
| Метрика | Хороший | Допустимый | Плохой |
|---|---|---|---|
| Размер APK (Android) | <25 МБ | 25-60 МБ | >60 МБ |
| Размер IPA (iOS) | <40 МБ | 40-80 МБ | >80 МБ |
| Холодный старт до интерактива | <1.5 с | 1.5-3 с | >3 с |
| Тёплый старт | <0.6 с | 0.6-1.2 с | >1.2 с |
Что обычно грузит размер
- Картинки и анимации. Lottie на 3 МБ, splash-видео на 8 МБ, иконки в PNG вместо vector. Часто половина бандла.
- Шрифты. 5 начертаний Roboto + Inter + кастомный — 6-12 МБ. Реально нужно 2-3 начертания.
- Огромные JS-бандлы в React Native без code splitting.
- Старые SDK-аналитики. AppMetrica + Yandex + Sentry + Firebase — каждый по 1-3 МБ.
- Карты в комплекте. Mapbox / Yandex MapKit — 8-15 МБ. Включать только если карта реально используется на 80% экранов.
- Native debug symbols в проде. Забыли отключить — +30 МБ.
Холодный старт — где теряем секунды
- Application.onCreate() / AppDelegate.didFinishLaunching с инициализацией 15 SDK подряд. Каждый — 50-200 мс.
- Сетевой запрос за конфигом до показа главного экрана. Splash крутится 2 секунды.
- Загрузка БД в main thread. Sqlite миграция 200 МБ → 3 секунды лага.
- Heavy reflection в DI (Hilt без AGP optimisation, Koin со слабой настройкой).
Что делать с размером
- App Bundle на Android — пользователь скачивает только под свою архитектуру и плотность экрана. Минус 30-50% от APK.
- App Thinning на iOS — встроено в App Store, нужно только разделить картинки на asset catalog.
- Картинки в WebP/HEIC, иконки в SVG.
- Lottie только для одного-двух ключевых моментов. Остальное — нативный AnimatedDrawable.
- Аудит SDK раз в полгода. Что-то всегда оказывается ненужным.
- R8 / ProGuard с агрессивной настройкой. Минус 15-30% от размера.
Что делать с cold start
- Lazy init SDK. Sentry, AppMetrica и др. — после первого экрана, не в Application.onCreate.
- Splash без сетевых запросов. Конфиг — из локального кэша, обновление в фоне.
- Baseline Profiles на Android — компилируйте критический путь до AOT. Минус 20-30% к запуску.
- Удалить ContentProvider'ы от старых SDK — они тормозят запуск.
- Native binary size — strip. Если не делается в pipeline, делается вручную.
Как мерить
Android — adb shell am start -W возвращает TotalTime. iOS — os_signpost + Instruments. Для долгой картины — Firebase Performance Monitoring (если работает) или AppMetrica.
Вывод
Размер <25 МБ APK / <40 МБ IPA и cold start <1.5 секунды — реалистичный таргет для большинства приложений. Главные тяжеловесы: картинки, шрифты, SDK, native binaries. Главные таймеры: цепочка SDK в Application.onCreate, сетевой запрос на splash, миграции БД. Аудит раз в полгода — нормально, реже — приложение незаметно толстеет на 2-5 МБ в квартал.