Cold Start es el ciclo completo de inicio de una aplicación Android que comienza desde un estado cero, cuando el proceso de la aplicación no existe en la memoria y la Activity no se ha creado. El sistema crea un nuevo proceso, carga las clases, inicializa la Application, crea la Activity y realiza el primer dibujado. Según Google, 2024, el inicio en frío en dispositivos de gama media puede tardar de 1 a 5 segundos, y cada 100 ms de retraso reducen la probabilidad de retención del usuario en un 3%.
Puntos clave
Cold Start (inicio en frío) es un escenario en el que una aplicación Android se inicia desde el estado más inicial: el sistema operativo crea un nuevo proceso (fork de Zygote), asigna memoria, carga el código DEX en ART, inicializa las clases y crea una instancia de Application, y luego la primera Activity. Antes del inicio de la app, no hay datos sobre ella en la memoria del dispositivo, excepto las imágenes de clase en caché si se usa Background Dexopt.
El inicio en frío ocurre en tres casos: en el primer inicio después de instalar la aplicación, al iniciar después de reiniciar el dispositivo, y al iniciar después de que el sistema haya eliminado el proceso por falta de memoria. En dispositivos con 2–4 GB de RAM, el sistema elimina los procesos en segundo plano de forma bastante agresiva, por lo que Cold Start puede ocurrir cada vez que el usuario vuelve a la aplicación después de varias horas de inactividad. En Android 12+, el sistema puede mantener un proceso congelado (freeze / cached), pero con el ahorro activo de memoria (OOM-killer), el proceso será eliminado.
Según Google (informe Find My Device, 2023), el 65% de los usuarios cierran una aplicación si no se abre en 3 segundos. Para las redes sociales y mensajería, donde los usuarios vuelven docenas de veces al día, Cold Start afecta directamente a la retención. En Google Play Console, la métrica Cold Start forma parte de la sección Android Vitals y se muestra como uno de los indicadores de ANR y rendimiento. Una aplicación que supera el umbral de Cold Start “malo” (más de 5 segundos en el 25% de los dispositivos) recibe una advertencia en la consola y puede ser degradada en los resultados de búsqueda.
Android distingue tres tipos de inicio de aplicación, cada uno con diferente duración, impacto en UX y enfoques de optimización. Comprender la diferencia es esencial para elegir la estrategia de perfilado correcta.
| Tipo de inicio | Estado del proceso | Application.onCreate | Tiempo típico |
|---|---|---|---|
| Cold | Sin proceso | Se ejecuta | 1–5 segundos |
| Warm | Proceso existe, sin Activity | No se ejecuta | 200–600 ms |
| Hot | Proceso + Activity en memoria | No se ejecuta | < 200 ms |
Warm Start ocurre cuando el proceso de la aplicación ya existe en segundo plano, pero la Activity ha sido destruida (por ejemplo, el usuario volvió después de una pausa larga y el sistema liberó la memoria de la Activity). Hot Start — cuando el usuario minimiza la aplicación y la abre inmediatamente: la Activity está en pausa y la restauración toma un tiempo mínimo. Para el usuario, Cold Start es el tipo de inicio más notable, y su optimización proporciona la mayor mejora en UX.
Cold Start puede convertirse en Warm Start después de que la aplicación se haya iniciado al menos una vez — ART almacena en caché las imágenes de clase compiladas (Image in Boot Profile) y la carga posterior de DEX es más rápida. Por lo tanto, el segundo inicio después del primer Cold Start suele ser un 20–40% más rápido. Si la aplicación usa Baseline Profiles, los perfiles se cargan en el primer inicio y el segundo inicio puede ser aún más rápido: Google Play, que publicó Baseline Profiles, aceleró Cold Start en un 30% en dispositivos con Android 12+.
Cold Start consta de fases estrictamente definidas, cada una de las cuales puede medirse y optimizarse de forma independiente. Conocer las fases ayuda a determinar en qué etapa la aplicación pierde tiempo. Google identifica cuatro fases principales: creación del proceso, inicialización de Application, creación de Activity y primer fotograma.
El sistema Android (ActivityManagerService) crea un nuevo proceso mediante fork del proceso Zygote. Zygote es un proceso precargado con clases comunes de Android. El fork tarda 30–80 ms — este tiempo está fuera del control de la aplicación. Después del fork, se inicia ActivityThread — la instancia del bucle principal de la aplicación. En esta etapa también ocurre la carga de clases a través de ClassLoader, y ART comienza a interpretar el primer bytecode. Si la aplicación usa muchos inicializadores estáticos, esta fase puede prolongarse.
Inmediatamente después de que ActivityThread se inicia, se llama a Application.onCreate. Aquí es donde los desarrolladores suelen cometer el error de inicializar todo a la vez: Crashlytics, Firebase, clientes de red, bases de datos, componentes Dagger, contenedores DI. Cada una de estas inicializaciones bloquea el hilo principal. Si Application.onCreate tarda 500 ms, el usuario ve una pantalla blanca (o negra) durante medio segundo. La duración óptima de esta fase es de menos de 200 ms en un dispositivo de gama media.
Después de la inicialización de Application, se crea una instancia de Activity (MainActivity o Launcher Activity). Se llama a Activity.onCreate, donde ocurren setContentView, la inicialización de fragmentos, la configuración de ViewModel y la suscripción a LiveData/Flow. Si onCreate carga datos (SharedPreferences, SQLite, API) de forma síncrona en el hilo principal, la fase se extiende. El objetivo es mantener onCreate en 200–400 ms en un dispositivo de gama media.
Después de que onCreate finaliza, comienza el primer renderizado: medida, layout, draw. Este momento se llama TTFD (Time To First Draw). Si la aplicación usa una pantalla de inicio (a través de SplashScreen API en Android 12+ o mediante theme), el renderizado puede ocurrir más rápido, pero el usuario aún esperará hasta que desaparezca el splash. El TTFD ideal para Cold Start es de menos de 1.5 segundos.
Medir Cold Start requiere herramientas especiales, ya que el registro normal (Log.d) solo comienza a funcionar después de la creación de Application, y la temporización del fork y la carga de clases permanece inaccesible. Google recomienda tres métodos: comandos ADB, Android Vitals y macros personalizadas de rendimiento.
El método más simple y reproducible es el comando adb shell am start -S -W. La bandera -S detiene forzosamente la aplicación antes del inicio (garantiza Cold Start). El comando muestra tres métricas: ThisTime (tiempo de inicio de Activity), TotalTime (tiempo total incluyendo el inicio del proceso) y WaitTime (tiempo incluyendo todas las demoras del Activity Manager). Para mediciones limpias, realice 5–7 lecturas y use la mediana — las lecturas individuales están sujetas a ruido (CPU throttling, carga en segundo plano).
# Cold Start forzado con medición
$ adb shell am start -S -W \
com.example.app/.MainActivity
# Salida del comando:
# ThisTime: 1842 ms
# TotalTime: 1842 ms
# WaitTime: 1855 ms
Google Play Console recopila métricas anónimas de todos los dispositivos donde está instalada la aplicación. En la sección Android Vitals → Launch time se muestra la distribución mediana de Cold Start por modelo de dispositivo y versión de Android. Esta es la única forma de ver métricas reales en dispositivos de usuarios, no solo en dispositivos de prueba. Si Cold Start supera los 5 segundos en Redmi 9A (2 GB RAM) y 1.2 segundos en Pixel 8, el problema es el tamaño de la memoria y la cantidad de clases. Google también muestra el retraso perceptible por el usuario basado en el percentil 25.
Google Jetpack Macrobenchmark (biblioteca androidx.benchmark) permite escribir pruebas instrumentadas de inicio de aplicación. La prueba instala la aplicación, la inicia desde un estado en frío y mide el tiempo hasta el primer fotograma. Macrobenchmark ejecuta automáticamente 20 iteraciones, descarta valores atípicos y muestra percentiles estables. Para CI/CD, puede comparar el inicio de línea base y el actual — si el tiempo aumenta, el pipeline de CI puede fallar.
Optimizar Cold Start es un trabajo sistemático que afecta varios niveles de la aplicación: código, recursos, configuración de compilación y arquitectura de inicialización. Google recomienda comenzar por lo más costoso — Application.onCreate — y avanzar hacia los detalles más pequeños.
Traslade toda la inicialización que no se requiere al inicio fuera de Application.onCreate al primer punto de uso. Firebase, Crashlytics, SDK de análisis, notificaciones push, componentes DI — todo puede inicializarse después de renderizar la primera pantalla. Use Lazy (by lazy) en Kotlin o inicialización mediante ContentProvider con una llamada explícita initialize(context). Según Google (Android Performance, 2023), la inicialización perezosa reduce Cold Start en un 40–60% para aplicaciones que usan 5+ SDK.
Baseline Profiles son la compilación AOT de clases y métodos críticos utilizados al iniciar la aplicación. Sin Baseline Profiles, ART interpreta el código DEX o lo compila mediante JIT, lo que lleva tiempo. Con los perfiles, ART compila los métodos especificados en código nativo (AOT) durante la instalación de la aplicación. Google afirma que Baseline Profiles aceleran Cold Start en un 15–40% en Android 9+ y hasta un 60% con optimizaciones ART de Android 12+. Para crear perfiles, use el plugin androidx.benchmark:benchmark-baseline-profile-gradle-plugin.
La biblioteca androidx.startup permite ordenar la inicialización de componentes y ejecutarla en un solo ContentProvider. En lugar de múltiples ContentProviders de diferentes bibliotecas (cada uno añade 1–2 ms al inicio en frío), App Startup los combina en un grafo de dependencias e inicializa estrictamente según sea necesario. Al inicio solo se ejecutan los componentes marcados con @Initializer que son necesarios para la primera pantalla. Para los demás se establece la bandera needEarlyInit = false — se inician después del primer renderizado.
// App Startup Initializer — inicialización después del inicio
class AnalyticsInitializer : Initializer<Unit> {
override fun create(context: Context) {
Analytics.init(context)
}
override fun dependencies() = listOf<Class<out Initializer<*>>>()
}
// En AndroidManifest.xml marcar como opcional
// <meta-data android:name="AnalyticsInitializer"
// android:value="false" />
El tamaño del archivo DEX afecta directamente el tiempo de carga de ART. Use R8/ProGuard para ofuscación y eliminación de código muerto (MinifyEnabled = true). Active android:extractNativeLibs="false" en el manifiesto para que el APK no desempaquete archivos .so al instalarse. Para proyectos con más de 10 seguimientos de referencia, agregue startup-priority solo para la primera pantalla. Cada método adicional en DEX añade 0.5–2 ms a la carga, y para aplicaciones con más de 50k métodos (multidex con primary dex) — hasta 300 ms.
Android Vitals en Google Play Console (sección Launch time) recopila datos de todos los dispositivos donde está instalada la aplicación, siempre que el usuario haya dado su consentimiento para el diagnóstico anónimo. Las métricas se dividen en tres categorías: “bueno”, “moderado”, “malo”, según el tiempo de Cold Start.
Google define Cold Start “malo” como un tiempo superior a 5 segundos en cualquier dispositivo. Sin embargo, en la práctica, para dispositivos insignia (Snapdragon 8 Gen), un buen tiempo es inferior a 1.5 segundos, para gama media — inferior a 2.5 segundos, para gama baja — inferior a 4 segundos. Android Vitals muestra la mediana por cada modelo de dispositivo, lo que permite entender en qué dispositivos la aplicación inicia lentamente. Si Cold Start es malo en dispositivos Samsung A-series o Xiaomi Redmi, la causa suele ser la memoria flash lenta y la poca RAM (la aceleración mediante Baseline Profiles da el mayor efecto precisamente en estos dispositivos).
Además de mostrarse en la consola, la métrica Cold Start afecta la calificación de calidad de la aplicación en Google Play Search. Las aplicaciones con un alto porcentaje de inicios “malos” reciben una etiqueta de “Advertencia de rendimiento” en la página de instalación, lo que reduce la conversión. Según Google (Android Performance Playbook, 2024), las aplicaciones que resolvieron los problemas de Cold Start aumentan la conversión de instalación en un promedio del 5% y mejoran la retención (D1) en un 3–7%.
Para un monitoreo más detallado, use Firebase Performance Monitoring. Realiza un seguimiento de Cold Start a nivel de sesión, desglosado por versión de la aplicación y versión de Android. A diferencia de Android Vitals, Firebase muestra un diagrama de traza del tiempo invertido por fase. Por ejemplo, se puede ver que en la versión 3.2.0, Application.onCreate tomó 800 ms (debido a una nueva biblioteca de notificaciones push), mientras que en la versión 3.2.1 — 200 ms (después de la corrección).
A continuación se presentan dos ejemplos prácticos que aceleran directamente Cold Start: trasladar la inicialización de SDK después del inicio y usar SplashScreen API.
Un error típico es inicializar todos los SDK en Application.onCreate. A continuación se muestra cómo trasladar la inicialización no crítica a una corrutina que se lanza después de dibujar el primer fotograma. Importante: Firebase, Crashlytics y los SDK de Crash Reporting deben inicializarse al inicio — no pueden diferirse porque capturan fallos durante la inicialización de otros componentes. Para el resto, use lifecycleScope en la primera Activity.
// ❌ Malo — toda la inicialización en Application.onCreate
class App : Application() {
override fun onCreate() {
super.onCreate()
Firebase.init(this) // crítico
Analytics.init(this) // puede ser después
Database.init(this) // puede ser después
ImageLoader.init(this) // puede ser después
}
}
// ✅ Bueno — Firebase al inicio, el resto after inflate
class App : Application() {
override fun onCreate() {
super.onCreate()
Firebase.init(this)
}
}
// En MainActivity después del primer fotograma:
lifecycleScope.launchWhenResumed {
initializeNonCriticalSdks()
}
En Android 12+, use la API oficial SplashScreen API, que muestra un splash del sistema (icono de la aplicación sobre un fondo oscuro/claro) inmediatamente al iniciar el proceso. Esto oculta el tiempo de inicialización al usuario — ve un splash en lugar de una pantalla blanca. Para dispositivos antiguos, use theme-based splash (Theme.SplashScreen en estilos). Importante: el splash no debe durar más de 300 ms — si la aplicación no está lista para entonces, dibuje un esqueleto “persistente” (shimmer) y muestre el progreso de carga.
// 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 basado en tema (Android 5-11)
// En themes.xml:
// <style name="Theme.App.Starting" parent="Theme.SplashScreen">
// <item name="windowSplashScreenBackground">@color/white</item>
// <item name="windowSplashScreenAnimatedIcon">@mipmap/ic_launcher</item>
// </style>
Preguntas frecuentes
El emulador usa un potente ordenador anfitrión y emula el procesador con aceleración por hardware (HAXM / WHPX). Los dispositivos físicos, especialmente los de gama baja (almacenamiento eMMC en lugar de UFS), tienen una E/S mucho más lenta. Se recomienda medir Cold Start en un dispositivo físico de gama media para obtener datos realistas.
Según las recomendaciones de Google, la mediana de Cold Start debe ser inferior a 2 segundos en dispositivos de gama media. Para los insignia — inferior a 1.5 segundos. Para dispositivos de gama baja (2 GB RAM) se permite hasta 4 segundos, pero se recomienda optimizar a 3 segundos. Los valores superiores a 5 segundos se consideran críticos.
Indirectamente — sí. Si el manifiesto contiene un icono vectorial (AdaptiveIcon), debe compilarse en un drawable al inicio. Si el icono contiene rutas complejas (pathData con docenas de curvas), la compilación tarda 10–30 ms. Use VectorDrawable con pathData optimizado (mediante SVGOMG o Android Studio Vector Asset).
Sí, si un Feature Module (Android App Bundle) se carga bajo demanda, su Cold Start se mide desde el momento en que se toca la función hasta el primer fotograma. Los módulos bajo demanda se cargan mediante Play Core Library y su instalación añade 500–3000 ms al tiempo de inicio. Optimice el código de la función igual que el módulo principal.
Las aplicaciones con más de 64k métodos requieren Multidex. Esto significa que ART debe cargar múltiples archivos DEX, lo que aumenta el tiempo de Cold Start en 200–800 ms dependiendo de la cantidad de archivos classes.dex. Use minSdk 21+ (ART con soporte nativo de multidex) y configure primary dex mediante --main-dex-list para mantener las clases críticas en el primer archivo DEX.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también