Misurare le prestazioni
Profiler, trace e benchmark
Misurare le prestazioni è una lezione Android Academy gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Android Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Android Academy include 4 lezioni in totale.
Misurare prima di ottimizzare
La regola d'oro delle attività sulle prestazioni è: misurare prima, non tirare mai a indovinare. L'intuizione umana su ciò che è lento è quasi sempre sbagliata.
In questa lezione imparerà a utilizzare gli strumenti che Android mette a disposizione per osservare le prestazioni: profiler, trace di sistema e microbenchmark. Una volta che sarà in grado di misurare, ogni ottimizzazione diventerà una decisione basata sui dati anziché un'ipotesi.
- I profiler mostrano CPU, memoria ed energia in tempo reale.
- I trace di sistema rivelano esattamente come viene impiegato il tempo di ogni frame.
- I benchmark forniscono valori ripetibili che può confrontare tra diverse build.
Il budget di 16 ms per frame
Su uno schermo a 60 Hz, il sistema disegna un nuovo frame ogni 16,67 ms. Se l'app non riesce a preparare un frame entro questo intervallo, il frame viene perso e gli utenti percepiscono del jank (scatti). Sui dispositivi a 120 Hz, il budget si riduce a circa 8 ms.
Ottimizzare le prestazioni significa restare entro questo budget. Il commento qui sotto mostra il calcolo da tenere a mente.
// Frame budget math
// 60 Hz -> 1000ms / 60 = 16.67ms per frame
// 90 Hz -> 1000ms / 90 = 11.11ms per frame
// 120 Hz -> 1000ms / 120 = 8.33ms per frame
//
// Exceed the budget on the UI thread = a dropped frame = visible jank.
fun frameBudgetMs(refreshHz: Int): Double = 1000.0 / refreshHz
fun main() {
println("60Hz -> %.2f ms".format(frameBudgetMs(60)))
println("120Hz -> %.2f ms".format(frameBudgetMs(120)))
}Android Studio Profiler
Android Studio Profiler (View > Tool Windows > Profiler) si collega a un'app in esecuzione e mostra timeline in tempo reale per CPU, memoria, energia e rete.
- CPU: registra tracce dei metodi e tracce di sistema per individuare i percorsi di codice più dispendiosi.
- Memoria: monitora le allocazioni e acquisisce heap dump per trovare le perdite.
- Energia: individua wakelock eccessivi e job che consumano la batteria.
Esegua sempre il profiling di una build simile a quella di release su un dispositivo reale. Le build di debug e gli emulatori forniscono valori fuorvianti perché le ottimizzazioni sono disabilitate.
Macrobenchmark per scenari reali
La libreria Jetpack Macrobenchmark misura interi percorsi utente (avvio, scorrimento, navigazione) su un dispositivo reale e restituisce metriche stabili, come la temporizzazione dei frame e il tempo di avvio.
Si scrive un test che avvia l'app ed esegue un flusso; la libreria lo ripete molte volte e fornisce i valori della mediana e del 99° percentile.
@RunWith(AndroidJUnit4::class)
class StartupBenchmark {
@get:Rule val rule = MacrobenchmarkRule()
@Test
fun coldStartup() = rule.measureRepeated(
packageName = "com.example.app",
metrics = listOf(StartupTimingMetric()),
iterations = 5,
startupMode = StartupMode.COLD
) {
pressHome()
startActivityAndWait()
}
}Microbenchmark per il codice critico
Quando serve sapere quanto è veloce una singola funzione, si utilizza la libreria Microbenchmark. Questa esegue il codice in un ciclo serrato, riscalda il JIT e restituisce i nanosecondi per operazione, eliminando il rumore dalle misurazioni.
La si utilizzi per parser, serializer, ordinamenti o qualsiasi helper vincolato dalla CPU che viene chiamato frequentemente.
@RunWith(AndroidJUnit4::class)
class JsonParseBenchmark {
@get:Rule val benchmarkRule = BenchmarkRule()
@Test
fun parseLargePayload() {
val raw = loadSampleJson()
benchmarkRule.measureRepeated {
val parsed = parseUsers(raw) // code under test
// assertEquals avoids the compiler dropping the result
assertTrue(parsed.isNotEmpty())
}
}
}Tracciamento di sistema con Perfetto
Il tracciamento di sistema registra ciò che ogni thread e il sistema eseguono, frame per frame. Il profiler della CPU di Android Studio può registrarne uno; in alternativa, è possibile acquisirlo con adb e aprirlo in Perfetto (ui.perfetto.dev).
Una traccia mostra i temuti frame rossi, il lavoro eseguito sul thread principale e il tempo trascorso nella GPU. È lo strumento migliore per diagnosticare il jank.
# Record a 5-second system trace from the command line
adb shell perfetto -o /data/misc/perfetto-traces/trace.perfetto-trace \
-t 5s sched freq idle am wm gfx view
# Pull it to your machine, then open in https://ui.perfetto.dev
adb pull /data/misc/perfetto-traces/trace.perfetto-traceSezioni di traccia personalizzate
Per impostazione predefinita, le tracce mostrano il lavoro del framework. Per contrassegnare il proprio codice, lo si racchiuda in una sezione di traccia con nome. Questi nomi compaiono poi come blocchi etichettati in Perfetto, rendendo facile individuare i punti critici.
Utilizzi l'API androidx.tracing, così le sezioni compariranno sia nelle tracce di debug sia in quelle dei benchmark.
import androidx.tracing.trace
fun loadDashboard(repo: Repo): Dashboard {
return trace("loadDashboard") {
val user = trace("fetchUser") { repo.user() }
val feed = trace("fetchFeed") { repo.feed() }
Dashboard(user, feed)
}
}
// In Perfetto you will now see named slices:
// loadDashboard > fetchUser, fetchFeedMonitoraggio dei frame persi durante l'esecuzione
Non sempre si dispone di un profiler collegato. JankStats è una libreria Jetpack che segnala i frame con jank dall'interno dell'app in esecuzione, consentendo di registrarli o inviare aggregazioni agli strumenti di analisi.
Si collega alla finestra e richiama il codice ogni volta che un frame supera il proprio budget.
val jankStats = JankStats.createAndTrack(window) { frameData ->
if (frameData.isJank) {
Log.w("Jank", "Janky frame: ${frameData.frameDurationUiNanos} ns")
analytics.logJank(frameData.frameDurationUiNanos)
}
}
// Pause/resume with your screen lifecycle
override fun onResume() { super.onResume(); jankStats.isTrackingEnabled = true }
override fun onPause() { super.onPause(); jankStats.isTrackingEnabled = false }Interpretare i numeri: i percentili
Una singola media nasconde i problemi. Se il frame medio dura 10 ms ma il 99° percentile è di 40 ms, l'1% dei frame presenta jank e gli utenti lo percepiscono. Osservi sempre P50, P90, P99, non solo la media.
I benchmark li calcolano automaticamente. L'helper qui sotto mostra il concetto usando campioni grezzi dei frame.
fun percentile(samplesMs: List<Double>, p: Int): Double {
val sorted = samplesMs.sorted()
val index = ((p / 100.0) * (sorted.size - 1)).toInt()
return sorted[index]
}
fun main() {
val frames = listOf(8.0, 9.0, 10.0, 9.5, 11.0, 40.0, 9.0, 10.5)
println("P50 = %.1f ms".format(percentile(frames, 50)))
println("P99 = %.1f ms".format(percentile(frames, 99)))
}Un flusso di misurazione ripetibile
Valori attendibili derivano da un processo rigoroso. Segua ogni volta questa checklist:
- Utilizzi una build release / non debuggable (R8 abilitato).
- Esegua il test su un dispositivo fisico, collegato all'alimentazione e con uno stato termico stabile.
- Ripeta lo scenario diverse volte e riporti la mediana.
- Modifichi una sola cosa alla volta e misuri nuovamente.
- Confronti i risultati con una baseline salvata, così da poter dimostrare il miglioramento.
Se salta questi passaggi, finirà per inseguire il rumore invece di risolvere problemi reali.
Dove va davvero il tempo
La maggior parte del jank su Android deriva da un piccolo insieme di cause. Conoscerle indica dove puntare gli strumenti:
- Lavoro sul thread principale: operazioni su disco/rete/JSON nel thread dell'interfaccia.
- Ricomposizione eccessiva: Compose ridisegna una quantità eccessiva di elementi.
- Allocazioni continue: pause dovute alla garbage collection.
- Passaggi di layout: layout profondamente annidati o misurati ripetutamente.
Le prossime lezioni del corso affrontano direttamente la ricomposizione, le perdite di memoria e l'avvio. La misurazione indica quale problema risolvere per primo.
Verifica rapida
Si desidera una misurazione stabile e ripetibile della durata dell'avvio a freddo dell'app su un dispositivo reale, eseguita su più avvii. Quale strumento è più adatto?
Riepilogo: ora sa misurare
Ha imparato a rendere le prestazioni visibili prima di modificare qualsiasi cosa:
- Il budget di 16 ms per frame determina la differenza tra fluidità e jank.
- Android Studio Profiler mostra CPU, memoria ed energia in tempo reale.
- I Macrobenchmark e i Microbenchmark forniscono valori ripetibili.
- Le tracce Perfetto e le sezioni
trace()personalizzate rivelano dove viene impiegato il tempo. - JankStats segnala il jank dall'interno dell'app in esecuzione.
- Legga P50/P90/P99, esegua il profiling delle build release su dispositivi reali e modifichi una sola cosa alla volta.
Ora applichiamo tutto questo a una delle principali cause del jank in Compose: la ricomposizione.
Domande Frequenti
La lezione «Misurare le prestazioni» è gratuita?
Sì — il testo completo di «Misurare le prestazioni» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Android Academy, passa a CoddyKit PRO. Il corso Android Academy include 4 lezioni in totale.
Cosa imparerò in «Misurare le prestazioni»?
Profiler, trace e benchmark Eserciti Android Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Android Academy?
Non è richiesta alcuna esperienza precedente. Android Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.
Quanto tempo richiede la lezione «Misurare le prestazioni»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Android Academy?
Sì. Ogni lezione Android Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Misurare le prestazioni
- Domare la ricomposizione
- Memory leak e soluzioni
- Avvio e profili baseline