Cold Start est le cycle complet de démarrage d'une application Android qui commence à partir d'un état zéro, lorsque le processus de l'application n'existe pas en mémoire et que l'Activity n'a pas été créée. Le système crée un nouveau processus, charge les classes, initialise l'Application, crée l'Activity et effectue le premier dessin. Selon Google, 2024, le démarrage à froid sur les appareils de milieu de gamme peut prendre de 1 à 5 secondes, et chaque 100 ms de retard réduit la probabilité de rétention de l'utilisateur de 3%.
Points clés
Cold Start (démarrage à froid) est un scénario dans lequel une application Android est lancée à partir de l'état le plus initial : le système d'exploitation crée un nouveau processus (fork de Zygote), alloue de la mémoire, charge le code DEX dans ART, initialise les classes et crée une instance d'Application, puis la première Activity. Avant le lancement de l'application, aucune donnée la concernant n'est présente dans la mémoire de l'appareil, à l'exception des images de classe mises en cache si Background Dexopt est utilisé.
Le démarrage à froid se produit dans trois cas : lors du premier lancement après l'installation de l'application, lors du lancement après un redémarrage de l'appareil, et lors du lancement après que le système a supprimé le processus par manque de mémoire. Sur les appareils avec 2 à 4 Go de RAM, le système supprime les processus en arrière-plan de manière assez agressive, donc Cold Start peut se produire chaque fois que l'utilisateur revient à l'application après plusieurs heures d'inactivité. Sous Android 12+, le système peut conserver un processus gelé (freeze / cached), mais avec une économie de mémoire active (OOM-killer), le processus sera terminé.
Selon Google (rapport Find My Device, 2023), 65% des utilisateurs ferment une application si elle ne s'ouvre pas en 3 secondes. Pour les réseaux sociaux et les messageries, où les utilisateurs reviennent des dizaines de fois par jour, Cold Start affecte directement la rétention. Dans Google Play Console, la métrique Cold Start fait partie de la section Android Vitals et est affichée comme l'un des indicateurs ANR et de performance. Une application qui dépasse le seuil de Cold Start « mauvais » (plus de 5 secondes sur 25% des appareils) reçoit un avertissement dans la console et peut être déclassée dans les résultats de recherche.
Android distingue trois types de lancement d'application, chacun avec une durée, un impact sur l'UX et des approches d'optimisation différents. Comprendre la différence est essentiel pour choisir la stratégie de profilage correcte.
| Type de lancement | État du processus | Application.onCreate | Temps typique |
|---|---|---|---|
| Cold | Aucun processus | Exécuté | 1 à 5 secondes |
| Warm | Processus existe, pas d'Activity | Non exécuté | 200 à 600 ms |
| Hot | Processus + Activity en mémoire | Non exécuté | < 200 ms |
Warm Start se produit lorsque le processus de l'application existe déjà en arrière-plan, mais que l'Activity a été détruite (par exemple, l'utilisateur est revenu après une longue pause et le système a libéré la mémoire de l'Activity). Hot Start — lorsque l'utilisateur minimise l'application et l'ouvre immédiatement : l'Activity est en pause et la restauration prend un temps minimal. Pour l'utilisateur, Cold Start est le type de lancement le plus notable, et son optimisation apporte la plus grande amélioration de l'UX.
Cold Start peut devenir Warm Start après que l'application a été lancée au moins une fois — ART met en cache les images de classe compilées (Image dans Boot Profile) et le chargement DEX suivant est plus rapide. Par conséquent, le deuxième lancement après le premier Cold Start est généralement 20 à 40% plus rapide. Si l'application utilise Baseline Profiles, les profils sont chargés lors du premier lancement et le deuxième démarrage peut être encore plus rapide : Google Play, qui a publié Baseline Profiles, a accéléré Cold Start de 30% sur les appareils avec Android 12+.
Cold Start se compose de phases strictement définies, chacune pouvant être mesurée et optimisée indépendamment. Connaître les phases aide à déterminer à quelle étape l'application perd du temps. Google identifie quatre phases principales : création du processus, initialisation de l'Application, création de l'Activity et première image.
Le système Android (ActivityManagerService) crée un nouveau processus par fork du processus Zygote. Zygote est un processus préchargé avec des classes Android communes. Le fork prend 30 à 80 ms — ce temps échappe au contrôle de l'application. Après le fork, ActivityThread est démarré — l'instance de la boucle principale de l'application. À cette étape, le chargement des classes a également lieu via ClassLoader, et ART commence à interpréter le premier bytecode. Si l'application utilise de nombreux initialiseurs statiques, cette phase peut s'allonger.
Immédiatement après le démarrage d'ActivityThread, Application.onCreate est appelé. C'est là que les développeurs commettent le plus souvent l'erreur d'initialiser tout à la fois : Crashlytics, Firebase, clients réseau, bases de données, composants Dagger, conteneurs DI. Chacune de ces initialisations bloque le thread principal. Si Application.onCreate prend 500 ms, l'utilisateur voit un écran blanc (ou noir) pendant une demi-seconde. La durée optimale de cette phase est inférieure à 200 ms sur un appareil de milieu de gamme.
Après l'initialisation de l'Application, une instance d'Activity est créée (MainActivity ou Launcher Activity). Activity.onCreate est appelé, où se produisent setContentView, l'initialisation des fragments, la configuration du ViewModel et l'abonnement à LiveData/Flow. Si onCreate charge des données (SharedPreferences, SQLite, API) de manière synchrone sur le thread principal, la phase s'allonge. L'objectif est de maintenir onCreate entre 200 et 400 ms sur un appareil de milieu de gamme.
Après la fin d'onCreate, le premier rendu commence : mesure, layout, draw. Ce moment est appelé TTFD (Time To First Draw). Si l'application utilise un écran de démarrage (via l'API SplashScreen sur Android 12+ ou via un thème), le rendu peut se produire plus rapidement, mais l'utilisateur attendra toujours la disparition du splash. La TTFD idéale pour Cold Start est inférieure à 1,5 seconde.
Mesurer Cold Start nécessite des outils spéciaux, car la journalisation normale (Log.d) ne commence à fonctionner qu'après la création de l'Application, et le timing du fork et du chargement des classes reste inaccessible. Google recommande trois méthodes : les commandes ADB, Android Vitals et les macros de performance personnalisées.
La méthode la plus simple et la plus reproductible est la commande adb shell am start -S -W. Le drapeau -S arrête de force l'application avant le lancement (garantit Cold Start). La commande affiche trois métriques : ThisTime (temps de démarrage de l'Activity), TotalTime (temps total incluant le lancement du processus) et WaitTime (temps incluant tous les délais de l'Activity Manager). Pour des mesures propres, effectuez 5 à 7 lectures et utilisez la médiane — les lectures individuelles sont sujettes au bruit (limitation du CPU, charge en arrière-plan).
# Cold Start forcé avec mesure
$ adb shell am start -S -W \
com.example.app/.MainActivity
# Sortie de la commande :
# ThisTime: 1842 ms
# TotalTime: 1842 ms
# WaitTime: 1855 ms
Google Play Console collecte des métriques anonymes de tous les appareils sur lesquels l'application est installée. Dans la section Android Vitals → Launch time, la distribution médiane de Cold Start par modèle d'appareil et version d'Android est affichée. C'est le seul moyen de voir les métriques réelles sur les appareils des utilisateurs, et non seulement sur les appareils de test. Si Cold Start dépasse 5 secondes sur Redmi 9A (2 Go de RAM) et 1,2 seconde sur Pixel 8, le problème est la taille de la mémoire et le nombre de classes. Google affiche également le retard perceptible par l'utilisateur basé sur le 25e percentile.
Google Jetpack Macrobenchmark (bibliothèque androidx.benchmark) permet d'écrire des tests instrumentés de lancement d'application. Le test installe l'application, la lance à partir d'un état froid et mesure le temps jusqu'à la première image. Macrobenchmark exécute automatiquement 20 itérations, rejette les valeurs aberrantes et montre des percentiles stables. Pour CI/CD, vous pouvez comparer la ligne de base et le lancement actuel — si le temps augmente, le pipeline CI peut échouer.
Optimiser Cold Start est un travail systématique qui affecte plusieurs niveaux de l'application : code, ressources, configuration de build et architecture d'initialisation. Google recommande de commencer par la partie la plus coûteuse — Application.onCreate — et de progresser vers les petits détails.
Déplacez toute l'initialisation non requise au démarrage hors de Application.onCreate vers le premier point d'utilisation. Firebase, Crashlytics, SDK d'analyse, notifications push, composants DI — tout peut être initialisé après le rendu du premier écran. Utilisez Lazy (by lazy) en Kotlin ou l'initialisation via ContentProvider avec un appel explicite initialize(context). Selon Google (Android Performance, 2023), l'initialisation paresseuse réduit Cold Start de 40 à 60% pour les applications utilisant 5 SDK ou plus.
Baseline Profiles sont la compilation AOT des classes et méthodes critiques utilisées au démarrage de l'application. Sans Baseline Profiles, ART interprète le code DEX ou le compile via JIT, ce qui prend du temps. Avec les profils, ART compile les méthodes spécifiées en code natif (AOT) lors de l'installation de l'application. Google affirme que Baseline Profiles accélèrent Cold Start de 15 à 40% sur Android 9+ et jusqu'à 60% avec les optimisations ART d'Android 12+. Pour créer des profils, utilisez le plugin androidx.benchmark:benchmark-baseline-profile-gradle-plugin.
La bibliothèque androidx.startup permet d'ordonner l'initialisation des composants et de l'exécuter dans un seul ContentProvider. Au lieu de plusieurs ContentProviders de différentes bibliothèques (chacun ajoute 1 à 2 ms au démarrage à froid), App Startup les fusionne dans un graphe de dépendances et initialise strictement selon les besoins. Au démarrage, seuls les composants marqués avec @Initializer qui sont nécessaires pour le premier écran sont exécutés. Pour les autres, le drapeau needEarlyInit = false est défini — ils sont lancés après le premier rendu.
// App Startup Initializer — initialisation après le démarrage
class AnalyticsInitializer : Initializer<Unit> {
override fun create(context: Context) {
Analytics.init(context)
}
override fun dependencies() = listOf<Class<out Initializer<*>>>()
}
// Dans AndroidManifest.xml marquer comme optionnel
// <meta-data android:name="AnalyticsInitializer"
// android:value="false" />
La taille du fichier DEX affecte directement le temps de chargement d'ART. Utilisez R8/ProGuard pour l'obfuscation et la suppression de code mort (MinifyEnabled = true). Activez android:extractNativeLibs="false" dans le manifeste pour que l'APK ne décompresse pas les fichiers .so lors de l'installation. Pour les projets avec plus de 10 suivis de référence, ajoutez startup-priority uniquement pour le premier écran. Chaque méthode supplémentaire dans DEX ajoute 0,5 à 2 ms au chargement, et pour les applications avec plus de 50k méthodes (multidex avec primary dex) — jusqu'à 300 ms.
Android Vitals dans Google Play Console (section Launch time) collecte les données de tous les appareils sur lesquels l'application est installée, à condition que l'utilisateur ait consenti au diagnostic anonyme. Les métriques sont divisées en trois catégories : « bon », « modéré », « mauvais », selon le temps de Cold Start.
Google définit Cold Start « mauvais » comme un temps dépassant 5 secondes sur n'importe quel appareil. Cependant, en pratique, pour les appareils phares (Snapdragon 8 Gen), un bon temps est inférieur à 1,5 seconde, pour le milieu de gamme — inférieur à 2,5 secondes, pour l'entrée de gamme — inférieur à 4 secondes. Android Vitals affiche la médiane pour chaque modèle d'appareil, ce qui permet de comprendre sur quels appareils l'application démarre lentement. Si Cold Start est mauvais sur les appareils Samsung A-series ou Xiaomi Redmi, la cause est le plus souvent une mémoire flash lente et une faible RAM (l'accélération via Baseline Profiles donne le plus grand effet précisément sur ces appareils).
En plus de l'affichage dans la console, la métrique Cold Start affecte l'évaluation de la qualité de l'application dans Google Play Search. Les applications avec un pourcentage élevé de démarrages « mauvais » reçoivent une étiquette « Avertissement de performance » sur la page d'installation, ce qui réduit la conversion. Selon Google (Android Performance Playbook, 2024), les applications qui ont résolu les problèmes de Cold Start ont augmenté la conversion d'installation de 5% en moyenne et amélioré la rétention (D1) de 3 à 7%.
Pour une surveillance plus détaillée, utilisez Firebase Performance Monitoring. Il suit Cold Start au niveau de la session, ventilé par version d'application et version d'Android. Contrairement à Android Vitals, Firebase montre un diagramme de trace du temps passé par phase. Par exemple, vous pouvez voir que dans la version 3.2.0, Application.onCreate a pris 800 ms (en raison d'une nouvelle bibliothèque de notifications push), tandis que dans la version 3.2.1 — 200 ms (après la correction).
Voici deux exemples pratiques qui accélèrent directement Cold Start : déplacer l'initialisation des SDK après le démarrage et utiliser l'API SplashScreen.
Une erreur typique est d'initialiser tous les SDK dans Application.onCreate. Ci-dessous est montré comment déplacer l'initialisation non critique dans une coroutine qui se lance après le dessin de la première image. Important : Firebase, Crashlytics et les SDK de rapport de crash doivent être initialisés au démarrage — ils ne peuvent pas être différés car ils capturent les crashes lors de l'initialisation d'autres composants. Pour le reste, utilisez lifecycleScope dans la première Activity.
// ❌ Mauvais — toute l'initialisation dans Application.onCreate
class App : Application() {
override fun onCreate() {
super.onCreate()
Firebase.init(this) // critique
Analytics.init(this) // peut être plus tard
Database.init(this) // peut être plus tard
ImageLoader.init(this) // peut être plus tard
}
}
// ✅ Bon — Firebase au démarrage, le reste after inflate
class App : Application() {
override fun onCreate() {
super.onCreate()
Firebase.init(this)
}
}
// Dans MainActivity après la première image :
lifecycleScope.launchWhenResumed {
initializeNonCriticalSdks()
}
Sous Android 12+, utilisez l'API officielle SplashScreen qui affiche un splash système (icône de l'application sur fond sombre/clair) immédiatement au démarrage du processus. Cela cache le temps d'initialisation à l'utilisateur — il voit un splash au lieu d'un écran blanc. Pour les anciens appareils, utilisez theme-based splash (Theme.SplashScreen dans les styles). Important : le splash ne doit pas durer plus de 300 ms — si l'application n'est pas prête d'ici là, dessinez un squelette « persistant » (shimmer) et affichez la progression du chargement.
// 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)
}
}
// Splash basé sur le thème (Android 5-11)
// Dans themes.xml :
// <style name="Theme.App.Starting" parent="Theme.SplashScreen">
// <item name="windowSplashScreenBackground">@color/white</item>
// <item name="windowSplashScreenAnimatedIcon">@mipmap/ic_launcher</item>
// </style>
Questions fréquentes
L'émulateur utilise un ordinateur hôte puissant et émule le processeur avec accélération matérielle (HAXM / WHPX). Les appareils physiques, surtout ceux d'entrée de gamme (stockage eMMC au lieu d'UFS), ont des E/S beaucoup plus lentes. Il est recommandé de mesurer Cold Start sur un appareil physique de milieu de gamme pour obtenir des données réalistes.
Selon les recommandations de Google, le Cold Start médian doit être inférieur à 2 secondes sur les appareils de milieu de gamme. Pour les phares — inférieur à 1,5 seconde. Pour les appareils d'entrée de gamme (2 Go de RAM), jusqu'à 4 secondes est acceptable, mais une optimisation à 3 secondes est recommandée. Les valeurs supérieures à 5 secondes sont considérées comme critiques.
Indirectement — oui. Si le manifeste contient une icône vectorielle (AdaptiveIcon), elle doit être compilée en drawable au démarrage. Si l'icône contient des chemins complexes (pathData avec des dizaines de courbes), la compilation prend 10 à 30 ms. Utilisez VectorDrawable avec un pathData optimisé (via SVGOMG ou Android Studio Vector Asset).
Oui, si un Feature Module (Android App Bundle) est chargé à la demande, son Cold Start est mesuré depuis le moment où l'on tape sur la fonctionnalité jusqu'à la première image. Les modules à la demande sont chargés via Play Core Library et leur installation ajoute 500 à 3000 ms au temps de démarrage. Optimisez le code de la fonctionnalité de la même manière que le module principal.
Les applications avec plus de 64k méthodes nécessitent Multidex. Cela signifie qu'ART doit charger plusieurs fichiers DEX, ce qui augmente le temps de Cold Start de 200 à 800 ms selon le nombre de fichiers classes.dex. Utilisez minSdk 21+ (ART avec support natif de multidex) et configurez primary dex via --main-dex-list pour conserver les classes critiques dans le premier fichier DEX.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi