Cold Start — avvio a freddo e ottimizzazione in Android

Autore: IT Sectr Pubblicato: 2026-03-31 Tempo di lettura: 9 min

Cold Start è il ciclo completo di avvio di un'applicazione Android che parte da uno stato zero, quando il processo dell'applicazione non esiste in memoria e l'Activity non è stata creata. Il sistema crea un nuovo processo, carica le classi, inizializza l'Application, crea l'Activity ed esegue il primo disegno. Secondo Google, 2024, l'avvio a freddo sui dispositivi di fascia media può richiedere da 1 a 5 secondi e ogni 100 ms di ritardo riducono la probabilità di fidelizzazione dell'utente del 3%.

Punti chiave

  • Cold Start — avvio di un'app Android da zero: nuovo processo, caricamento classi, inizializzazione
  • Metrica misurata dall'avvio del processo al primo disegno (TTID o TTFD)
  • Fasi dell'avvio: creazione del processo → Application.onCreate → Activity.onCreate → primo fotogramma
  • Ottimizzazione include inizializzazione pigra, Baseline Profiles e riduzione della dimensione DEX
  • Google Play utilizza Cold Start come uno degli indicatori chiave in Android Vitals

Cos'è Cold Start

Cold Start (avvio a freddo) è uno scenario in cui un'applicazione Android viene avviata dallo stato più iniziale: il sistema operativo crea un nuovo processo (fork da Zygote), alloca memoria, carica il codice DEX in ART, inizializza le classi e crea un'istanza di Application, quindi la prima Activity. Prima dell'avvio dell'app, non ci sono dati su di essa nella memoria del dispositivo, tranne le immagini della classe memorizzate nella cache se viene utilizzato Background Dexopt.

Quando si verifica Cold Start

L'avvio a freddo si verifica in tre casi: al primo avvio dopo l'installazione dell'app, all'avvio dopo il riavvio del dispositivo e all'avvio dopo che il sistema ha rimosso il processo per mancanza di memoria. Sui dispositivi con 2–4 GB di RAM, il sistema rimuove i processi in background in modo abbastanza aggressivo, quindi Cold Start può verificarsi ogni volta che l'utente torna all'app dopo diverse ore di inattività. Su Android 12+, il sistema può mantenere un processo congelato (freeze / cached), ma con il risparmio attivo della memoria (OOM-killer), il processo verrà terminato.

Perché Cold Start è una metrica critica

Secondo Google (rapporto Find My Device, 2023), il 65% degli utenti chiude un'app se non si apre entro 3 secondi. Per i social network e i messenger, dove gli utenti tornano decine di volte al giorno, Cold Start influisce direttamente sulla fidelizzazione. In Google Play Console, la metrica Cold Start fa parte della sezione Android Vitals e viene visualizzata come uno degli indicatori ANR e di prestazione. Un'app che supera la soglia di Cold Start “pessimo” (più di 5 secondi sul 25% dei dispositivi) riceve un avviso nella console e può essere declassata nei risultati di ricerca.

Cold Start vs Warm Start vs Hot Start

Android distingue tre tipi di avvio dell'app, ciascuno con durata, impatto sull'UX e approcci di ottimizzazione diversi. Comprendere la differenza è essenziale per scegliere la giusta strategia di profilazione.

Tipo di avvioStato del processoApplication.onCreateTempo tipico
ColdNessun processoEseguito1–5 secondi
WarmProcesso esistente, nessuna ActivityNon eseguito200–600 ms
HotProcesso + Activity in memoriaNon eseguito< 200 ms

Warm Start si verifica quando il processo dell'app esiste già in background, ma l'Activity è stata distrutta (ad esempio, l'utente è tornato dopo una lunga pausa e il sistema ha liberato la memoria dell'Activity). Hot Start — quando l'utente minimizza l'app e la riapre immediatamente: l'Activity è in pausa e il ripristino richiede un tempo minimo. Per l'utente, Cold Start è il tipo di avvio più evidente e la sua ottimizzazione porta il maggior miglioramento dell'UX.

Transizione tra i tipi

Cold Start può diventare Warm Start dopo che l'app è stata avviata almeno una volta — ART memorizza nella cache le immagini delle classi compilate (Image in Boot Profile) e il successivo caricamento DEX è più veloce. Pertanto, il secondo avvio dopo il primo Cold Start è generalmente del 20–40% più veloce. Se l'app utilizza Baseline Profiles, i profili vengono caricati al primo avvio e il secondo avvio può essere ancora più veloce: Google Play, che ha pubblicato Baseline Profiles, ha accelerato Cold Start del 30% sui dispositivi con Android 12+.

Fasi dell'avvio a freddo

Cold Start consiste in fasi rigorosamente definite, ciascuna delle quali può essere misurata e ottimizzata indipendentemente. Conoscere le fasi aiuta a determinare in quale stadio l'app sta perdendo tempo. Google identifica quattro fasi principali: creazione del processo, inizializzazione dell'Application, creazione dell'Activity e primo fotogramma.

Fase 1: Creazione del processo (fork)

Il sistema Android (ActivityManagerService) crea un nuovo processo tramite fork dal processo Zygote. Zygote è un processo precaricato con le classi comuni di Android. Il fork richiede 30–80 ms — questo tempo è fuori dal controllo dell'app. Dopo il fork, viene avviato ActivityThread — l'istanza del ciclo principale dell'applicazione. In questa fase avviene anche il caricamento delle classi tramite ClassLoader e ART inizia a interpretare il primo bytecode. Se l'app utilizza molti inizializzatori statici, questa fase può prolungarsi.

Fase 2: Application.onCreate

Subito dopo l'avvio di ActivityThread, viene chiamato Application.onCreate. Qui è dove gli sviluppatori commettono più spesso l'errore di inizializzare tutto in una volta: Crashlytics, Firebase, client di rete, database, componenti Dagger, contenitori DI. Ciascuna di queste inizializzazioni blocca il thread principale. Se Application.onCreate richiede 500 ms, l'utente vede una schermata bianca (o nera) per mezzo secondo. La durata ottimale di questa fase è inferiore a 200 ms su un dispositivo di fascia media.

Fase 3: Activity.onCreate

Dopo l'inizializzazione dell'Application, viene creata un'istanza di Activity (MainActivity o Launcher Activity). Viene chiamato Activity.onCreate, dove si verificano setContentView, l'inizializzazione dei fragment, la configurazione di ViewModel e la sottoscrizione a LiveData/Flow. Se onCreate carica dati (SharedPreferences, SQLite, API) in modo sincrono sul thread principale, la fase si estende. L'obiettivo è mantenere onCreate entro 200–400 ms su un dispositivo di fascia media.

Fase 4: Primo fotogramma (TTFD)

Dopo il completamento di onCreate, inizia il primo rendering: misura, layout, draw. Questo momento è chiamato TTFD (Time To First Draw). Se l'app utilizza una schermata splash (tramite SplashScreen API su Android 12+ o tramite tema), il rendering può avvenire più velocemente, ma l'utente aspetterà comunque che lo splash scompaia. La TTFD ideale per Cold Start è inferiore a 1,5 secondi.

Come misurare Cold Start

Misurare Cold Start richiede strumenti speciali, poiché la registrazione normale (Log.d) inizia a funzionare solo dopo la creazione dell'Application e la tempistica del fork e del caricamento delle classi rimane inaccessibile. Google raccomanda tre metodi: comandi ADB, Android Vitals e macro di performance personalizzate.

Misurazione tramite ADB

Il metodo più semplice e riproducibile è il comando adb shell am start -S -W. Il flag -S ferma forzatamente l'app prima dell'avvio (garantisce Cold Start). Il comando restituisce tre metriche: ThisTime (tempo di avvio dell'Activity), TotalTime (tempo totale inclusivo dell'avvio del processo) e WaitTime (tempo inclusivo di tutti i ritardi di Activity Manager). Per misurazioni pulite, effettuare 5–7 letture e utilizzare la mediana — le letture singole sono soggette a rumore (CPU throttling, carico in background).

bash
# Cold Start forzato con misurazione
$ adb shell am start -S -W \
    com.example.app/.MainActivity

# Output del comando:
# ThisTime: 1842 ms
# TotalTime: 1842 ms
# WaitTime: 1855 ms

Android Vitals (Google Play Console)

Google Play Console raccoglie metriche anonime da tutti i dispositivi in cui l'app è installata. Nella sezione Android Vitals → Launch time, viene visualizzata la distribuzione mediana di Cold Start per modello di dispositivo e versione Android. Questo è l'unico modo per vedere le metriche reali sui dispositivi degli utenti, non solo sui dispositivi di test. Se Cold Start supera 5 secondi su Redmi 9A (2 GB RAM) e 1,2 secondi su Pixel 8, il problema è la dimensione della memoria e il numero di classi. Google mostra anche il ritardo percepibile dall'utente basato sul 25esimo percentile.

Macrobenchmark

Google Jetpack Macrobenchmark (libreria androidx.benchmark) consente di scrivere test strumentati di avvio dell'app. Il test installa l'app, la avvia da uno stato a freddo e misura il tempo fino al primo fotogramma. Macrobenchmark esegue automaticamente 20 iterazioni, scarta i valori anomali e mostra percentili stabili. Per CI/CD, puoi confrontare la baseline e l'avvio corrente — se il tempo aumenta, la pipeline CI può fallire.

Come ottimizzare Cold Start

Ottimizzare Cold Start è un lavoro sistematico che interessa diversi livelli dell'app: codice, risorse, configurazione di build e architettura di inizializzazione. Google raccomanda di iniziare dalla parte più costosa — Application.onCreate — e procedere verso i dettagli più piccoli.

Inizializzazione pigra (Lazy Init)

Sposta tutta l'inizializzazione non richiesta all'avvio fuori da Application.onCreate al primo punto di utilizzo. Firebase, Crashlytics, SDK di analisi, notifiche push, componenti DI — tutto può essere inizializzato dopo il rendering della prima schermata. Usa Lazy (by lazy) in Kotlin o l'inizializzazione tramite ContentProvider con una chiamata esplicita initialize(context). Secondo Google (Android Performance, 2023), l'inizializzazione pigra riduce Cold Start del 40–60% per le app che utilizzano 5+ SDK.

Baseline Profiles

Baseline Profiles sono la compilazione AOT di classi e metodi critici utilizzati all'avvio dell'app. Senza Baseline Profiles, ART interpreta il codice DEX o lo compila tramite JIT, richiedendo tempo. Con i profili, ART compila i metodi specificati in codice nativo (AOT) durante l'installazione dell'app. Google afferma che Baseline Profiles accelerano Cold Start del 15–40% su Android 9+ e fino al 60% con le ottimizzazioni ART di Android 12+. Per creare profili, usa il plugin androidx.benchmark:benchmark-baseline-profile-gradle-plugin.

App Startup Library

La libreria androidx.startup consente di ordinare l'inizializzazione dei componenti ed eseguirla in un unico ContentProvider. Invece di più ContentProvider di diverse librerie (ciascuno aggiunge 1–2 ms all'avvio a freddo), App Startup li unisce in un grafo di dipendenze e inizializza rigorosamente secondo necessità. All'avvio vengono eseguiti solo i componenti contrassegnati con @Initializer che sono necessari per la prima schermata. Per gli altri, viene impostato il flag needEarlyInit = false — vengono avviati dopo il primo rendering.

kotlin
// App Startup Initializer — inizializzazione dopo l'avvio
class AnalyticsInitializer : Initializer<Unit> {
    override fun create(context: Context) {
        Analytics.init(context)
    }
    override fun dependencies() = listOf<Class<out Initializer<*>>>()
}

// In AndroidManifest.xml marcare come opzionale
// <meta-data android:name="AnalyticsInitializer"
//     android:value="false" />

Riduzione della dimensione DEX

La dimensione del file DEX influisce direttamente sul tempo di caricamento di ART. Usa R8/ProGuard per offuscamento e rimozione del codice morto (MinifyEnabled = true). Attiva android:extractNativeLibs="false" nel manifest in modo che l'APK non decomprima i file .so durante l'installazione. Per progetti con più di 10 tracciamenti di riferimento, aggiungi startup-priority solo per la prima schermata. Ogni metodo extra in DEX aggiunge 0,5–2 ms al caricamento e per le app con più di 50k metodi (multidex con primary dex) — fino a 300 ms.

Cold Start in Android Vitals

Android Vitals in Google Play Console (sezione Launch time) raccoglie dati da tutti i dispositivi in cui l'app è installata, a condizione che l'utente abbia acconsentito alla diagnostica anonima. Le metriche sono divise in tre categorie: “buono”, “moderato”, “pessimo”, a seconda del tempo di Cold Start.

Soglie di Google

Google definisce Cold Start “pessimo” come un tempo superiore a 5 secondi su qualsiasi dispositivo. Tuttavia, in pratica, per i dispositivi di punta (Snapdragon 8 Gen), un buon tempo è inferiore a 1,5 secondi, per la fascia media — inferiore a 2,5 secondi, per la fascia bassa — inferiore a 4 secondi. Android Vitals mostra la mediana per ciascun modello di dispositivo, permettendo di capire su quali dispositivi l'app si avvia lentamente. Se Cold Start è pessimo sui dispositivi Samsung A-series o Xiaomi Redmi, la causa è molto spesso la memoria flash lenta e la scarsa RAM (l'accelerazione tramite Baseline Profiles dà il maggior effetto proprio su tali dispositivi).

Come Google Play utilizza la metrica

Oltre alla visualizzazione nella console, la metrica Cold Start influisce sulla valutazione della qualità dell'app in Google Play Search. Le app con un'alta percentuale di avvii “pessimi” ricevono un'etichetta “Avviso di prestazioni” sulla pagina di installazione, riducendo la conversione. Secondo Google (Android Performance Playbook, 2024), le app che hanno risolto i problemi di Cold Start hanno aumentato la conversione di installazione in media del 5% e migliorato la fidelizzazione (D1) del 3–7%.

Integrazione con Firebase Performance

Per un monitoraggio più dettagliato, usa Firebase Performance Monitoring. Tiene traccia di Cold Start a livello di sessione, suddiviso per versione dell'app e versione di Android. A differenza di Android Vitals, Firebase mostra un diagramma di traccia del tempo speso per fase. Ad esempio, puoi vedere che nella versione 3.2.0, Application.onCreate ha richiesto 800 ms (a causa di una nuova libreria di notifiche push), mentre nella versione 3.2.1 — 200 ms (dopo la correzione).

Esempi di codice per l'ottimizzazione

Di seguito sono riportati due esempi pratici che accelerano direttamente Cold Start: spostare l'inizializzazione degli SDK dopo l'avvio e utilizzare SplashScreen API.

Spostare l'inizializzazione da Application.onCreate

Un errore tipico è inizializzare tutti gli SDK in Application.onCreate. Di seguito è mostrato come spostare l'inizializzazione non critica in una coroutine che viene avviata dopo il disegno del primo fotogramma. Importante: Firebase, Crashlytics e gli SDK di segnalazione crash devono essere inizializzati all'avvio — non possono essere ritardati perché catturano i crash durante l'inizializzazione di altri componenti. Per il resto, usa lifecycleScope nella prima Activity.

kotlin
// ❌ Pessimo — tutta l'inizializzazione in Application.onCreate
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        Firebase.init(this) // critico
        Analytics.init(this) // può essere dopo
        Database.init(this) // può essere dopo
        ImageLoader.init(this) // può essere dopo
    }
}

// ✅ Buono — Firebase all'avvio, il resto after inflate
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        Firebase.init(this)
    }
}

// In MainActivity dopo il primo fotogramma:
lifecycleScope.launchWhenResumed {
    initializeNonCriticalSdks()
}

SplashScreen API

Su Android 12+, usa l'API ufficiale SplashScreen che mostra uno splash di sistema (icona dell'app su sfondo scuro/chiaro) immediatamente all'avvio del processo. Questo nasconde il tempo di inizializzazione all'utente — vede uno splash invece di una schermata bianca. Per i dispositivi più vecchi, usa theme-based splash (Theme.SplashScreen negli stili). Importante: lo splash non dovrebbe durare più di 300 ms — se l'app non è pronta entro quel momento, disegna uno scheletro “persistente” (shimmer) e mostra l'avanzamento del caricamento.

kotlin
// 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 basato su tema (Android 5-11)
// In themes.xml:
// <style name="Theme.App.Starting" parent="Theme.SplashScreen">
//   <item name="windowSplashScreenBackground">@color/white</item>
//   <item name="windowSplashScreenAnimatedIcon">@mipmap/ic_launcher</item>
// </style>

Domande frequenti

Perché Cold Start sull'emulatore è più veloce che sul dispositivo?

L'emulatore utilizza un potente computer host ed emula il processore con accelerazione hardware (HAXM / WHPX). I dispositivi fisici, specialmente quelli di fascia bassa (memoria eMMC invece di UFS), hanno I/O molto più lento. Si consiglia di misurare Cold Start su un dispositivo fisico di fascia media per ottenere dati realistici.

Quale Cold Start è considerato accettabile?

Secondo le raccomandazioni di Google, il Cold Start mediano dovrebbe essere inferiore a 2 secondi sui dispositivi di fascia media. Per i flagship — inferiore a 1,5 secondi. Per i dispositivi di fascia bassa (2 GB RAM) sono accettabili fino a 4 secondi, ma si consiglia di ottimizzare a 3 secondi. I valori superiori a 5 secondi sono considerati critici.

La dimensione dell'icona influisce sulla velocità di Cold Start?

Indirettamente — sì. Se il manifest contiene un'icona vettoriale (AdaptiveIcon), deve essere compilata in un drawable all'avvio. Se l'icona contiene percorsi complessi (pathData con decine di curve), la compilazione richiede 10–30 ms. Usa VectorDrawable con pathData ottimizzato (tramite SVGOMG o Android Studio Vector Asset).

È necessario ottimizzare Cold Start nei Feature Module?

Sì, se un Feature Module (Android App Bundle) viene caricato su richiesta, il suo Cold Start viene misurato dal momento in cui si tocca la funzionalità al primo fotogramma. I moduli su richiesta vengono caricati tramite Play Core Library e la loro installazione aggiunge 500–3000 ms al tempo di avvio. Ottimizza il codice della funzionalità come faresti con il modulo principale.

Come influisce Multidex su Cold Start?

Le app con più di 64k metodi richiedono Multidex. Ciò significa che ART deve caricare più file DEX, aumentando il tempo di Cold Start di 200–800 ms a seconda del numero di file classes.dex. Usa minSdk 21+ (ART con supporto nativo multidex) e configura primary dex tramite --main-dex-list per mantenere le classi critiche nel primo file DEX.

Riepilogo

  • Cold Start — avvio completo dell'app con creazione di un nuovo processo, tempo 1–5 secondi
  • Misurato tramite ADB shell am start -S -W o Macrobenchmark in CI/CD
  • Quattro fasi: fork → Application.onCreate → Activity.onCreate → primo fotogramma
  • Ottimizzazione: inizializzazione pigra, Baseline Profiles, App Startup Library, compressione R8
  • Google Play valuta Cold Start come “pessimo” quando il tempo supera 5 secondi su qualsiasi dispositivo
  • SplashScreen API su Android 12+ nasconde il tempo di inizializzazione dietro uno splash di sistema
  • Ogni 100 ms di ritardo riducono la fidelizzazione dell'utente del 3%

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche