Rallentamento nello sviluppo — cos’è, cause e metodi di ottimizzazione

Autore: IT Sectr Pubblicato: 2026-07-28 Tempo di lettura: 8 min

Rallentamento è la descrizione da parte dell’utente di una situazione in cui un’app mobile funziona lentamente e in modo irregolare: a volte risponde normalmente, a volte si blocca improvvisamente per alcuni secondi. Nel contesto tecnico, “rallentamento” significa una combinazione di lag e micro-blocchi causati da frequenti pause GC, blocco del thread principale da operazioni sincrone e strutture dati non ottimali. Secondo la Android Performance Benchmarking Guide, ridurre il tempo di risposta da 300 ms a 100 ms aumenta la fidelizzazione degli utenti del 25%. Diagnosticare i rallentamenti richiede una combinazione di profilazione CPU e Memoria con analisi della frequenza di garbage collection.

Punti chiave

  • Rallentamento è un rallentamento intermittente dell’app, che si alterna a prestazioni normali
  • Cause principali — pause GC frequenti, operazioni sincrone nel thread UI, grandi volumi di dati negli adattatori senza paginazione
  • Diagnosi richiede CPU Profiler per trovare colli di bottiglia e Memory Profiler per analizzare frequenza e durata del GC
  • Risoluzione include l’implementazione della paginazione (Paging 3), l’ottimizzazione delle query SQL tramite Room e lo scarico di compiti pesanti su WorkManager
  • Prevenzione — Benchmark Baseline Profiles, compilazione AOT, minimizzazione delle allocazioni nei percorsi di codice caldi

Cosa significa “rallentamento” nello sviluppo mobile

Rallentamento è un termine informale che gli utenti usano per descrivere prestazioni dell’app soggettivamente lente. A differenza di un lag, che si manifesta come un ritardo costante, il rallentamento consiste in blocchi irregolari: l’app può funzionare perfettamente per diversi secondi e poi “pensare” per 1–3 secondi.

Descrizione tecnica del fenomeno

Dal punto di vista della profilazione, il rallentamento si manifesta come una serie di frame saltati (jank) con picchi di ritardo superiori a 100 ms. In un grafico FPS, questo appare come cali improvvisi: 60 → 20 → 55 → 10 frame al secondo. A differenza di un lag con FPS uniformemente basso, il rallentamento ha una variabilità pronunciata.

Percezione dell’utente

Quando un’app rallenta, l’utente non comprende la logica dei rallentamenti: lo schermo può scorrere fluidamente e poi fermarsi improvvisamente per un secondo. Questo causa frustrazione e riduce la fiducia nell’app. Secondo Google, il 53% degli utenti abbandona un sito o un’app se il caricamento richiede più di 3 secondi.

Cause di rallentamenti improvvisi nelle app

La natura intermittente del rallentamento indica che il problema è causato da fattori guidati da eventi, non da sovraccarico costante. Esaminiamo gli scenari tipici.

Pause GC durante l’allocazione di oggetti

Su Android, nell’ambiente ART, la garbage collection ferma tutti i thread dell’app. Se il codice crea molti oggetti temporanei — ad esempio, creando una nuova String tramite concatenazione a ogni chiamata onBindViewHolder — il GC viene eseguito più frequentemente. Una pausa può durare 5–50 ms a seconda della dimensione dell’heap e della generazione degli oggetti. L’utente percepisce questo come un improvviso “pensare”.

Query SQL sincrone nel thread UI

Room su Android e Core Data su iOS supportano query asincrone, ma gli sviluppatori spesso chiamano getValue() o eseguono query tramite runBlocking per semplicità. Una SELECT pesante con join su una tabella di 10.000 righe può richiedere 200–500 ms, bloccando completamente l’UI durante quel periodo.

Decodifica dell’immagine senza ridimensionamento

Caricare un’immagine della fotocamera (12 MP, 4000x3000 px) senza ridimensionamento richiede fino a 200 ms per la decodifica in Bitmap. Se le immagini vengono caricate in modo asincrono ma senza un pool di thread limitato, eseguire 5–6 decodifiche contemporaneamente può sovraccaricare la CPU, causando rallentamenti migratori.

  • Android — concatenazione di stringhe nei cicli, creazione di oggetti nei percorsi caldi, Bitmap senza inSampleSize
  • iOS — pool di autorelease con molti oggetti, imageWithContentsOfFile senza ridimensionamento, URLSession sincrona
  • Multi-piattaforma — parsing JSON nel thread UI, caricamento di dati nel thread principale in attesa della risposta del server

Come diagnosticare i blocchi su Android e iOS

Diagnosticare i rallentamenti intermittenti è più difficile che diagnosticare i lag costanti perché il problema potrebbe non riprodursi a ogni esecuzione. È necessaria la raccolta di statistiche per un lungo periodo.

Memory Profiler con registrazione di eventi GC

Android Studio Memory Profiler mostra non solo l’utilizzo della memoria ma anche gli eventi GC: frequenza, tipo (Concurrent, Full), durata. Se il GC si verifica più di una volta ogni 5 secondi in stato inattivo — è un segno di allocazione eccessiva. Eseguire un heap dump al momento del rallentamento rivela quali oggetti stanno occupando la memoria.

Xcode Instruments con Allocation Tracking

Su iOS, usa il modello Allocations in Instruments per tracciare la creazione e il rilascio degli oggetti. Attiva Generations — permettono di fare snapshot dell’heap tra le azioni e vedere quali oggetti rimangono in memoria. Gli oggetti persistenti che non vengono rilasciati sono una fonte di accumulo di memoria e successive pause.

API JankStats su Android

JankStats è una libreria Android che raccoglie metriche dei frame saltati in tempo reale. Associa ogni jank allo scenario corrente (ad esempio, “scorrimento elenco”, “apertura schermata”), permettendo di capire quale azione specifica innesca il rallentamento.

Esempio di integrazione di JankStats per tracciare i blocchi su Android:

kotlin
class MainActivity : AppCompatActivity() {
    private lateinit var jankStats: JankStats

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        jankStats = JankStats.create(this.window.decorView) { frameData ->
            if (frameData.isJank()) {
                Log.w("Jank", "Duration=${frameData.durationMs}ms")
            }
        }
    }
}

Metodi per eliminare le prestazioni lente

Eliminare i rallentamenti richiede un lavoro mirato su ogni causa. Non esiste una soluzione universale — è necessaria l’analisi di profili di prestazioni specifici.

Implementazione della paginazione tramite Paging 3

Se un elenco contiene 1000+ elementi e tutti vengono caricati in una volta — è un rallentamento garantito. Paging 3 su Android e NSFetchedResultsController su iOS caricano i dati in porzioni man mano che l’utente scorre. L’utente vede solo i primi 10–20 elementi; il resto viene caricato in background.

Ottimizzazione di query SQL e indici

Room permette di profilare le query tramite lo Strumento di Ispezione in Android Studio: tempo di esecuzione, numero di righe restituite e piano di query sono visibili. L’aggiunta di indici sulle colonne WHERE e ORDER BY può ridurre il tempo di query da 300 ms a 5 ms. Su iOS, un controllo simile viene eseguito da Core Data Profiler in Instruments.

Scarico di compiti su WorkManager

Sincronizzazioni in background, download di file, elaborazione dati — tutto questo dovrebbe essere eseguito tramite WorkManager (Android) o Background Tasks (iOS). Se la sincronizzazione viene eseguita nel thread UI, l’app rallenterà durante l’esecuzione. WorkManager garantisce l’esecuzione su un thread in background con consapevolezza dello stato della batteria e della rete.

Esempio di sincronizzazione in background tramite WorkManager su Android:

kotlin
class SyncWorker(context: Context, params: WorkerParameters)
    : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {
        return try {
            Log.d("Sync", "Syncing data in background thread")
            syncData()
            Result.success()
        } catch (e: Exception) {
            Result.retry()
        }
    }
}

Prevenzione dei rallentamenti in fase di sviluppo

I rallentamenti possono essere prevenuti in fase di codifica seguendo i principi di una gestione efficiente della memoria e dei thread.

Baseline Profiles per la compilazione AOT

Baseline Profiles sono un elenco di classi e metodi che Android compila in anticipo (AOT) anziché JIT. Senza un profilo, ogni nuova schermata viene compilata alla prima apertura, causando un ritardo di 100–500 ms. Prepara un Baseline Profile per le schermate chiave e attiva la generazione in Gradle tramite il plugin baseline-profile-gradle-plugin.

Minimizzazione delle allocazioni nei percorsi caldi

Un percorso caldo è il codice eseguito su ogni frame: onBindViewHolder, draw, layoutSubviews. Evita di creare oggetti in questi metodi: usa pool di oggetti, StringBuilder invece della concatenazione, memorizza nella cache stringhe formattate e formattatori. Ogni allocazione extra avvicina il prossimo GC.

Profilazione tramite Baseline Profiles in CI

Aggiungi Macrobenchmark alla tua pipeline CI con uno scenario di scorrimento elenco e apertura schermata. Imposta una soglia: il 99° percentile del tempo di frame non deve superare 16 ms. Se la soglia viene superata — la build viene rifiutata fino all’ottimizzazione.

  • Android — Baseline Profiles, Macrobenchmark, JankStats, StrictMode con penaltyDeath
  • iOS — MetricKit, os_signpost, XCTMetric, Main Thread Checker nello schema Debug
  • Approccio generale — profilazione regolare, revisioni del codice incentrate sulle allocazioni nei percorsi caldi

Domande frequenti

In cosa si differenzia il rallentamento da un normale lag?

Un lag è un ritardo costante (ad esempio, 200 ms a ogni tocco). Rallentamento è intermittente: l’app funziona normalmente, poi rallenta improvvisamente per 1–3 secondi, poi torna normale. La causa sono fattori guidati da eventi come pause GC o query sincrone al database.

Come misurare la frequenza delle pause GC su Android?

Usa Memory Profiler in Android Studio: la scheda Memory mostra gli eventi GC con durata. Per il monitoraggio in produzione, integra Firebase Performance Monitoring con trace personalizzati. Su iOS, attiva Malloc Debug e segna le generazioni di allocazione in Instruments.

Le richieste di rete possono causare rallentamenti?

Indirettamente — sì. Se la risposta del server è in ritardo e l’UI la attende in modo sincrono, l’app si blocca. Se la richiesta è asincrona ma l’elaborazione della risposta viene eseguita nel thread UI — anche questo causerà rallentamenti. La soluzione è l’elaborazione asincrona con coroutine e indicatori di progresso.

In che modo Kotlin Multiplatform influisce sulle prestazioni?

Se usato in modo errato, KMP può generare oggetti wrapper eccessivi per l’interoperabilità. Su iOS, questo aumenta la frequenza di allocazione e, di conseguenza, le pause ARC. Usa @ObjCName, ottimizza expect/actual ed evita chiamate frequenti al codice condiviso dai percorsi caldi dell’UI.

Aiuta aumentare la dimensione dell’heap su Android?

Aumentare l’heap tramite android:largeHeap=”true” ritarda il GC ma non elimina la causa delle allocazioni. Quando il GC viene infine eseguito, la pausa sarà più lunga perché più oggetti devono essere attraversati. La soluzione è ridurre il numero di allocazioni, non espandere l’heap.

Riepilogo

  • Rallentamento è un rallentamento intermittente dell’app causato da fattori guidati da eventi (pause GC, query sincrone, decodifica immagini)
  • Diagnosi richiede Memory Profiler, JankStats su Android e Allocation Tracking in Instruments su iOS
  • Cause principali — pause GC frequenti, mancanza di paginazione, query SQL non ottimali ed elaborazione sincrona nel thread UI
  • Risoluzione — Paging 3, WorkManager, ottimizzazione degli indici DB, ridimensionamento immagini e minimizzazione delle allocazioni
  • Prevenzione — Baseline Profiles, Macrobenchmark, StrictMode, revisioni del codice con controllo dei percorsi caldi
  • Strumenti — JankStats, Firebase Performance, MetricKit per il monitoraggio dei rallentamenti in produzione
  • Raccomandazione: implementa esecuzioni regolari di Macrobenchmark in CI con una soglia di 16 ms al 99° percentile dei frame

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