Cold Start — это полный цикл запуска Android-приложения, начинающийся с нулевого состояния, когда процесс приложения не существует в памяти, а Activity не создавалась. Система создаёт новый процесс, загружает классы, инициализирует Application, создаёт Activity и выполняет первую отрисовку. По данным Google, 2024, холодный старт на устройствах среднего сегмента может занимать от 1 до 5 секунд, и каждые 100 мс задержки снижают вероятность удержания пользователя на 3%.
Главное
Cold Start (холодный запуск) — это сценарий, при котором Android-приложение запускается с самого начального состояния: операционная система создаёт новый процесс (fork из Zygote), выделяет память, загружает DEX-код в ART, инициализирует классы и создаёт экземпляр Application, а затем первую Activity. До старта приложения никаких данных о нём в памяти устройства нет, кроме кэшированных образов классов, если используется Background Dexopt.
Холодный запуск происходит в трёх случаях: при первом запуске после установки приложения, при запуске после перезагрузки устройства, и при запуске после того, как система выгрузила процесс из-за нехватки памяти. На устройствах с 2–4 ГБ ОЗУ система выгружает фоновые процессы достаточно агрессивно, поэтому Cold Start может происходить при каждом возврате в приложение через несколько часов простоя. В Android 12+ система может сохранять замороженный процесс (freeze / cached), но при активной экономии памяти (OOM-killer) процесс будет уничтожен.
По данным Google (Find My Device report, 2023), 65% пользователей закрывают приложение, если оно не открылось за 3 секунды. Для социальных сетей и мессенджеров, где пользователь возвращается десятки раз в день, Cold Start напрямую влияет на retention. В Google Play Console метрика Cold Start входит в раздел Android Vitals и отображается как один из показателей ANR и производительности. Приложение, превышающее порог "плохой" Cold Start (более 5 секунд на 25% устройств), получает предупреждение в консоли и может быть понижено в поиске.
Android различает три типа запуска приложения, каждый из которых имеет разную длительность, влияние на UX и подходы к оптимизации. Понимание разницы необходимо для выбора правильной стратегии профилирования.
| Тип запуска | Состояние процесса | Application.onCreate | Типичное время |
|---|---|---|---|
| Cold | Нет процесса | Выполняется | 1–5 секунд |
| Warm | Процесс есть, Activity нет | Не выполняется | 200–600 мс |
| Hot | Процесс + Activity в памяти | Не выполняется | < 200 мс |
Warm Start происходит, когда процесс приложения уже существует в фоне, но Activity была уничтожена (например, пользователь вернулся после долгой паузы, и система освободила память Activity). Hot Start — когда пользователь сворачивает приложение и сразу открывает его снова: Activity приостановлена и восстановление занимает минимальное время. Для пользователя Cold Start — самый заметный тип запуска, именно его оптимизация даёт наибольший прирост в UX.
Cold Start может стать Warm Start после того, как приложение было запущено хотя бы раз — ART кэширует скомпилированные образы классов (Image in Boot Profile) и повторная загрузка DEX происходит быстрее. Поэтому второй запуск после первого Cold Start обычно на 20–40% быстрее. Если приложение использует Baseline Profiles, профили загружаются при первом запуске и второй старт может быть ещё быстрее: Google Play, опубликовавший Baseline Profiles, ускорил Cold Start на 30% на устройствах с Android 12+.
Cold Start состоит из строго определённых фаз, каждая из которых может быть измерена и оптимизирована независимо. Знание фаз помогает определить, на каком этапе приложение теряет время. Google выделяет четыре основных фазы: создание процесса, инициализация Application, создание Activity и первый кадр.
Система Android (ActivityManagerService) создаёт новый процесс путём fork из процесса Zygote. Zygote — это предварительно загруженный процесс с common-классами Android. Fork выполняется за 30–80 мс — это время, которое приложение не может контролировать. После fork запускается ActivityThread — экземпляр главного цикла приложения. На этом этапе также происходит загрузка классов через ClassLoader, и ART начинает интерпретировать первый байт-код. Если приложение использует много статических инициализаторов, эта фаза может затянуться.
Сразу после старта ActivityThread вызывается Application.onCreate. Здесь разработчик чаще всего совершает ошибку, инициализируя всё сразу: Crashlytics, Firebase, сетевые клиенты, базы данных, Dagger-компоненты, DI-контейнеры. Каждая такая инициализация — это время, заблокированное на главном потоке. Если Application.onCreate выполняется 500 мс, все эти полсекунды пользователь видит белый (или чёрный) экран. Оптимальная длительность этой фазы — менее 200 мс на среднем устройстве.
После инициализации Application создаётся экземпляр Activity (MainActivity или Launcher Activity). Вызывается Activity.onCreate, где происходит setContentView, инциализация фрагментов, настройка ViewModel, подписка на LiveData/Flow. Если onCreate выполняет загрузку данных (SharedPreferences, SQLite, API) синхронно на главном потоке, фаза расширяется. Цель — уложить onCreate в 200–400 мс на среднем устройстве.
После завершения onCreate начинается первая отрисовка: мера, лэйаут, draw. Этот момент называется TTFD (Time To First Draw). Если приложение использует splash-экран (через SplashScreen API на Android 12+ или через theme), отрисовка может произойти быстрее, но пользователь всё равно будет ждать, пока splash скроется. Идеальный TTFD для Cold Start — менее 1.5 секунды.
Измерение Cold Start требует специальных инструментов, так как обычное логирование (Log.d) начинает работу только после создания Application, а тайминг fork и загрузки классов остаётся вне доступа. Google рекомендует три метода: ADB-команды, Android Vitals и кастомные макросы perf.
Самый простой и воспроизводимый способ — команда adb shell am start -S -W. Флаг -S принудительно останавливает приложение перед запуском (гарантирует Cold Start). Команда выводит три метрики: ThisTime (время старта Activity), TotalTime (суммарное время с учётом запуска процесса) и WaitTime (время с учётом всех задержек Activity Manager). Для чистоты измерения сделайте 5–7 замеров и возьмите медиану — единичные замеры подвержены шуму (CPU throttling, фоновая нагрузка).
# Принудительный Cold Start с замером
$ adb shell am start -S -W \
com.example.app/.MainActivity
# Вывод команды:
# ThisTime: 1842 ms
# TotalTime: 1842 ms
# WaitTime: 1855 ms
Google Play Console собирает анонимные метрики со всех устройств, где установлено приложение. В разделе Android Vitals → Launch time отображается медианное распределение Cold Start по модели устройства и версии Android. Это единственный способ увидеть реальные показатели на устройствах пользователей, а не на тестовых девайсах. Если на Redmi 9A (2 ГБ ОЗУ) Cold Start превышает 5 секунд, а на Pixel 8 — 1.2 секунды, проблема в объёме памяти и количестве классов. Google также показывает пользовательскую воспринимаемую задержку (user-perceptible delay) на основе 25 перцентиля.
Google Jetpack Macrobenchmark (библиотека androidx.benchmark) позволяет писать инструментированные тесты запуска приложения. Тест устанавливает приложение, запускает его с холодным состоянием и измеряет время до первого кадра. Macrobenchmark автоматически делает 20 прогонов, отбрасывает выбросы и показывает стабильные процентили. Для CI/CD можно сравнить baseline и текущий запуск — если время увеличилось, CI-пайплайн может падать.
Оптимизация Cold Start — это системная работа, затрагивающая несколько уровней приложения: код, ресурсы, конфигурацию сборки и архитектуру инициализации. Google рекомендует начинать с самого дорогого — Application.onCreate — и двигаться к мелочам.
Перенесите всю инициализацию, не требующуюся на старте, из Application.onCreate в первую точку использования. Firebase, Crashlytics, analytics SDK, push-notifications, DI-компоненты — всё можно инициализировать после отрисовки первого экрана. Используйте Lazy (by lazy) в Kotlin или ContentProvider-инициализацию с явным вызовом initialize(context). По данным Google (Android Performance, 2023), ленивая инициализация сокращает Cold Start на 40–60% для приложений, использующих 5+ SDK.
Baseline Profiles — это AOT-компиляция критических классов и методов, которые используются на старте приложения. Без Baseline Profiles ART интерпретирует DEX-код или компилирует его JIT'ом, что занимает время. С профилями ART компилирует указанные методы в нативный код (AOT) при установке приложения. Google утверждает, что Baseline Profiles дают ускорение Cold Start на 15–40% на Android 9+ и до 60% с ART-оптимизациями Android 12+. Для создания профилей используйте плагин androidx.benchmark:benchmark-baseline-profile-gradle-plugin.
Библиотека androidx.startup позволяет упорядочить инициализацию компонентов и выполнять её в одном ContentProvider. Вместо нескольких ContentProvider'ов от разных библиотек (каждый добавляет 1–2 мс к холодному старту) App Startup объединяет их в граф зависимостей и инициализирует строго по необходимости. На старте выполняются только компоненты с @Initializer, помеченные как необходимые для первого экрана. Для остальных устанавливается флаг needEarlyInit = false — они запускаются после первой отрисовки.
// App Startup Initializer — инициализация после старта
class AnalyticsInitializer : Initializer<Unit> {
override fun create(context: Context) {
Analytics.init(context)
}
override fun dependencies() = listOf<Class<out Initializer<*>>>()
}
// В AndroidManifest.xml отмечаем как необязательный
// <meta-data android:name="AnalyticsInitializer"
// android:value="false" />
Размер DEX-файла напрямую влияет на время его загрузки ART. Используйте R8/ProGuard для обфускации и удаления мёртвого кода (MinifyEnabled = true). Включите android:extractNativeLibs="false" в манифесте, чтобы APK не распаковывал .so файлы при установке. Для проектов с 10 Reference Tracking больше классов добавляйте startup-priority только для первого экрана. Каждый лишний метод в DEX добавляет 0.5–2 мс к загрузке, а для приложений с 50k+ методов (multidex с primary dex) — до 300 мс.
Android Vitals в Google Play Console (Launch time section) собирает данные со всех устройств, на которых установлено приложение, при условии согласия пользователя на анонимную диагностику. Метрики делятся на три категории: "good" (хороший), "moderate" (средний), "bad" (плохой), в зависимости от времени Cold Start.
Google определяет "bad" Cold Start как время, превышающее 5 секунд на любом устройстве. Однако на практике для флагманских устройств (Snapdragon 8 Gen) хорошим считается время менее 1.5 секунд, для среднего сегмента — менее 2.5 секунд, для бюджетного — менее 4 секунд. Android Vitals показывает медиану по каждому device model, что позволяет понять, на каких устройствах приложение запускается медленно. Если Cold Start плох на устройствах Samsung A-series или Xiaomi Redmi, причина чаще всего — слабая flash-память и малый объём ОЗУ (ускорение через Baseline Profiles даёт наибольший эффект именно на таких устройствах).
Помимо отображения в консоли, метрика Cold Start влияет на оценку качества приложения в Google Play Search. Приложения с высоким процентом "bad" запусков получают метку "Performance warning" на странице установки, что снижает конверсию. По данным Google (Android Performance Playbook, 2024), приложения, устранившие Cold Start-проблемы, в среднем увеличивают конверсию установки на 5% и улучшают показатель retention (D1) на 3–7%.
Для более детального мониторинга используйте Firebase Performance Monitoring. Он отслеживает Cold Start на уровне сессий, разбивает по версиям приложения и версиям Android. В отличие от Android Vitals, Firebase показывает trace-диаграмму затраченного времени по фазам. Например, можно увидеть, что на версии 3.2.0 Application.onCreate стал занимать 800 мс (из-за новой библиотеки push-уведомлений), а на версии 3.2.1 — 200 мс (после исправления).
Ниже приведены два практических примера, которые непосредственно ускоряют Cold Start: перенос инициализации SDK после старта и использование SplashScreen API.
Типичная ошибка — инициализация всех SDK в Application.onCreate. Ниже показано, как перенести некритичную инициализацию в корутину, которая запускается после отрисовки первого кадра. Важно: Firebase, Crashlytics и Crash Reporting SDK должны быть инициализированы на старте — их откладывать нельзя, так как они ловят краши при инициализации других компонентов. Для остальных используйте lifecycleScope при первой Activity.
// ❌ Плохо — вся инициализация в Application.onCreate
class App : Application() {
override fun onCreate() {
super.onCreate()
Firebase.init(this) // критично
Analytics.init(this) // можно позже
Database.init(this) // можно позже
ImageLoader.init(this) // можно позже
}
}
// ✅ Хорошо — Firebase на старте, остальное after inflate
class App : Application() {
override fun onCreate() {
super.onCreate()
Firebase.init(this)
}
}
// В MainActivity после первого кадра:
lifecycleScope.launchWhenResumed {
initializeNonCriticalSdks()
}
На Android 12+ используйте официальный SplashScreen API, который показывает system-сплэш (иконка приложения на тёмном/светлом фоне) сразу при старте процесса. Это скрывает время инициализации от пользователя — он видит сплэш, а не белый экран. Для старых устройств используйте theme-based splash (Theme.SplashScreen в стилях). Важно: сплэш не должен длиться дольше 300 мс — если за это время приложение не готово, нарисуйте "постоянный" скелетон (shimmer) и показывайте прогресс загрузки.
// SplashScreen API — Android 12+
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
val splashScreen = installSplashScreen()
splashScreen.setKeepOnScreenCondition {
isReady.value == false
}
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
// Theme-based splash (Android 5-11)
// В themes.xml:
// <style name="Theme.App.Starting" parent="Theme.SplashScreen">
// <item name="windowSplashScreenBackground">@color/white</item>
// <item name="windowSplashScreenAnimatedIcon">@mipmap/ic_launcher</item>
// </style>
Часто задаваемые вопросы
Эмулятор использует мощный хост-компьютер и эмулирует процессор с аппаратным ускорением (HAXM / WHPX). Физические устройства, особенно бюджетные (eMMC-память вместо UFS), имеют гораздо медленнее I/O. Рекомендуется измерять Cold Start на физическом устройстве среднего сегмента, чтобы получить реалистичные данные.
По рекомендациям Google, медианный Cold Start должен быть менее 2 секунд на устройствах среднего сегмента. Для флагманов — менее 1.5 секунд. Для бюджетных устройств (2 ГБ ОЗУ) допустимо до 4 секунд, но рекомендуется оптимизировать до 3 секунд. Значения более 5 секунд считаются критическими.
Косвенно — да. Если в манифесте указана vector-иконка (AdaptiveIcon), она должна быть скомпилирована в drawable при старте. Если иконка содержит сложные пути (pathData с десятками кривых), компиляция занимает 10–30 мс. Используйте VectorDrawable с оптимизированным pathData (через SVGOMG или Android Studio Vector Asset).
Да, если Feature Module (Android App Bundle) загружается по требованию (on-demand), его Cold Start считается от момента нажатия на фичу до первого кадра. On-demand модули загружаются через Play Core Library, и их установка добавляет 500–3000 мс к времени старта. Оптимизируйте код фичи так же, как и основной модуль.
Приложения с более чем 64k методов требуют Multidex. Это означает, что ART должен загрузить несколько DEX-файлов, что увеличивает время Cold Start на 200–800 мс в зависимости от количества classes.dex. Используйте minSdk 21+ (ART с поддержкой native multidex) и настройте primary dex через --main-dex-list, чтобы критические классы были в первом DEX-файле.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также