Mantenete la calma e lasciate che vi guidiamo attraverso ulteriori informazioni sul rendimento.
Ti diamo il benvenuto al terzo giorno della settimana di Performance Spotlight. Oggi continuiamo a condividere dettagli e indicazioni su aree importanti delle prestazioni dell'app. Tratteremo l'ottimizzazione guidata dal profilo, i miglioramenti delle prestazioni di Jetpack Compose e le considerazioni sul lavoro dietro le quinte. Iniziamo subito.
Ottimizzazione guidata dal profilo
I profili di baseline e i profili di avvio sono fondamentali per migliorare l'avvio e le prestazioni di runtime di un'app per Android. Fanno parte di un gruppo di ottimizzazioni del rendimento chiamato Ottimizzazione guidata dal profilo.
Quando un'app viene pacchettizzata, d8 dexer prende classi e metodi e compila i file classes.dex dell'app. Quando un utente apre l'app, questi file dex vengono caricati uno dopo l'altro finché l'app non può essere avviata. Fornendo un profilo di avvio, comunichi a d8 quali classi e metodi includere nei primi file classes.dex. Questa struttura consente all'app di caricare meno file, il che a sua volta migliora la velocità di avvio.
I profili di base spostano in modo efficace i passaggi di compilazione Just in Time (JIT) dai dispositivi degli utenti ai computer degli sviluppatori. Il codice compilato Ahead Of Time (AOT) ha dimostrato di ridurre sia il tempo di avvio sia i problemi di rendering.
Trello e profili di baseline
Abbiamo chiesto agli ingegneri dell'app Trello in che modo i profili di base hanno influito sulle prestazioni della loro app. Dopo aver applicato i profili di base al percorso utente principale, Trello ha registrato una riduzione significativa del 25 % del tempo di avvio dell'app.
Trello è riuscita a migliorare il tempo di avvio della sua app del 25 % utilizzando i profili di base.
Profili di base su Meta
Inoltre, gli ingegneri di Meta hanno recentemente pubblicato un articolo su come stanno accelerando le loro app per Android con i profili di base.
Nelle app di Meta, i team hanno notato un miglioramento di varie metriche critiche fino al 40 % dopo l'applicazione dei profili di base.
Miglioramenti tecnici come questi ti aiutano a migliorare la soddisfazione degli utenti e il successo dell'attività. La condivisione di queste informazioni con i proprietari dei prodotti, i CTO e i responsabili delle decisioni può anche contribuire ad accelerare le prestazioni della tua app.
Iniziare a utilizzare i profili di base
Per generare un profilo di base o di avvio, scrivi un test macrobenchmark che esercita l'app. Durante il test vengono raccolti i dati del profilo che verranno utilizzati durante la compilazione dell'app. I test sono scritti utilizzando la nuova API UiAutomator, che tratteremo domani.
Scrivere un benchmark come questo è semplice e puoi vedere l'esempio completo su GitHub.
@Test fun profileGenerator() { rule.collect( packageName = TARGET_PACKAGE, maxIterations = 15, stableIterations = 3, includeInStartupProfile = true ) { uiAutomator { startApp(TARGET_PACKAGE) } } }
Considerazioni
Inizia scrivendo un profilo di baseline e un profilo di avvio per il percorso più utilizzato dagli utenti. Ciò significa il punto di accesso principale che gli utenti utilizzano per accedere alla tua app, che di solito è dopo aver eseguito l'accesso. Poi continua a scrivere altri scenari di test per ottenere un quadro più completo solo per i profili di base. Non è necessario coprire tutto con un profilo di baseline. Attieniti ai percorsi più utilizzati e misura il rendimento sul campo. Scopri di più nel post di domani.
Iniziare a utilizzare l'ottimizzazione guidata dal profilo
Per scoprire come funzionano i profili di base, guarda questo video dell'Android Developers Summit:
Per un altro approfondimento, guarda l'episodio di Android Build Time sull'ottimizzazione guidata dal profilo:
Per approfondire l'argomento, sono disponibili anche guide dettagliate sui profili di baseline e sui profili di avvio.
Miglioramenti delle prestazioni di Jetpack Compose
Il framework UI per Android ha visto ripagarsi l'investimento in termini di prestazioni del team di ingegneria. A partire dalla versione 1.9 di Jetpack Compose, il jank di scorrimento è sceso allo 0,2 % durante un test di benchmark interno di scorrimento lungo.
Questi miglioramenti sono stati possibili grazie a diverse funzionalità incluse nelle release più recenti.
Finestra della cache personalizzabile
Per impostazione predefinita, i layout pigri compongono in anticipo un solo elemento nella direzione dello scorrimento e, dopo che un elemento è uscito dallo schermo, viene eliminato. Ora puoi personalizzare la quantità di elementi da conservare tramite una frazione dell'area visibile o delle dimensioni in dp. In questo modo, l'app esegue più lavoro in anticipo e, dopo aver attivato la composizione sospendibile tra i frame, utilizza il tempo disponibile in modo più efficiente.
Per iniziare a utilizzare le finestre della cache personalizzabili, crea un'istanza di LazyLayoutCacheWindow e passala all'elenco o alla griglia pigri. Misura il rendimento della tua app utilizzando diverse dimensioni della finestra della cache, ad esempio il 50% dell'area visibile. Il valore ottimale dipende dalla struttura dei contenuti e dalle dimensioni degli elementi.
val dpCacheWindow = LazyLayoutCacheWindow(ahead = 150.dp, behind = 100.dp)
val state = rememberLazyListState(cacheWindow = dpCacheWindow)
LazyColumn(state = state) {
// column contents
}Composizione in pausa
Questa funzionalità consente di mettere in pausa le composizioni e di suddividere il lavoro su più frame. Le API sono state introdotte nella versione 1.9 e ora vengono utilizzate per impostazione predefinita nella versione 1.10 nel recupero anticipato del layout pigro. Dovresti notare i maggiori vantaggi con gli elementi complessi con tempi di composizione più lunghi.
Altre ottimizzazioni delle prestazioni di Compose
Nelle versioni 1.9 e 1.10 di Compose, il team ha apportato anche diverse ottimizzazioni un po' meno evidenti.
Sono state migliorate diverse API che utilizzano le coroutine. Ad esempio, quando utilizzano Draggable e Clickable, gli sviluppatori dovrebbero notare tempi di reazione più rapidi e un numero maggiore di allocazioni.
Le ottimizzazioni nel monitoraggio del rettangolo di layout hanno migliorato il rendimento di modificatori come onVisibilityChanged() e onLayoutRectChanged(). In questo modo, la fase di layout viene accelerata, anche quando queste API non vengono utilizzate in modo esplicito.
Un altro miglioramento delle prestazioni è l'utilizzo di valori memorizzati nella cache durante l'osservazione delle posizioni tramite onPlaced().
Precaricare il testo in background
A partire dalla versione 1.9, Compose aggiunge la possibilità di precaricare il testo in un thread in background. In questo modo puoi precaricare le cache per consentire una disposizione del testo più rapida ed è pertinente per le prestazioni di rendering delle app. Durante il layout, il testo deve essere passato al framework Android, in cui viene compilata una cache di parole. Per impostazione predefinita, viene eseguito sul thread UI. Il trasferimento del recupero anticipato e del riempimento della cache delle parole a un thread in background può velocizzare il layout, soprattutto per i testi più lunghi. Per eseguire il precaricamento su un thread in background, puoi passare un executor personalizzato a qualsiasi componibile che utilizzi BasicText sotto il cofano passando un LocalBackgroundTextMeasurementExecutor a un CompositionLocalProvider come segue.
val defaultTextMeasurementExecutor = Executors.newSingleThreadExecutor()
CompositionLocalProvider(
LocalBackgroundTextMeasurementExecutor provides DefaultTextMeasurementExecutor
) {
BasicText("Some text that should be measured on a background thread!")
}A seconda del testo, questo può migliorare il rendering del testo. Per assicurarti che migliori il rendimento del rendering della tua app, esegui il benchmarking e confronta i risultati.
Considerazioni sul rendimento del lavoro in background
L'attività in background è una parte essenziale di molte app. Potresti utilizzare librerie come WorkManager o JobScheduler per eseguire attività quali:
- Caricamento periodico degli eventi di analisi
- Sincronizzazione dei dati tra un servizio di backend e un database
- Elaborazione dei contenuti multimediali (ad es. ridimensionamento o compressione delle immagini)
Una delle principali sfide durante l'esecuzione di queste attività è bilanciare le prestazioni e l'efficienza energetica. WorkManager ti consente di raggiungere questo equilibrio. È progettato per essere efficiente dal punto di vista energetico e per consentire di posticipare il lavoro a una finestra di esecuzione ottimale influenzata da una serie di fattori, inclusi i vincoli specificati o quelli imposti dal sistema.
Tuttavia, WorkManager non è una soluzione universale. Android dispone anche di una serie di API ottimizzate per il consumo energetico, progettate specificamente per determinati percorsi utente principali (CUJ) comuni.
Consulta la pagina di destinazione Attività in background per un elenco di alcune di queste attività, tra cui l'aggiornamento di un widget e l'ottenimento della posizione in background.
Strumenti di debug locali per il lavoro in background: scenari comuni
Per eseguire il debug di Background Work e capire perché un'attività potrebbe essere stata ritardata o non riuscita, devi avere visibilità su come il sistema ha pianificato le tue attività.
Per aiutarti in questo, WorkManager dispone di diversi strumenti correlati per eseguire il debug in locale e ottimizzare le prestazioni (alcuni di questi funzionano anche per JobScheduler). Ecco alcuni scenari comuni che potresti incontrare quando utilizzi WorkManager e una spiegazione degli strumenti che puoi utilizzare per eseguire il debug.
Debug del motivo per cui il lavoro pianificato non viene eseguito
Il ritardo o la mancata esecuzione del lavoro pianificato può essere dovuto a una serie di fattori, tra cui il mancato rispetto dei vincoli specificati o l'imposizione di vincoli da parte del sistema.
Il primo passo per capire perché il lavoro pianificato non viene eseguito è verificare che sia stato pianificato correttamente. Dopo aver confermato lo stato della pianificazione, determina se esistono vincoli o precondizioni non soddisfatti che impediscono l'esecuzione del lavoro.
Esistono diversi strumenti per eseguire il debug di questo scenario.
Background Task Inspector
Background Task Inspector è un potente strumento integrato direttamente in Android Studio. Fornisce una rappresentazione visiva di tutte le attività WorkManager e dei relativi stati (In esecuzione, In coda, Non riuscita, Riuscita).
Per eseguire il debug del motivo per cui il lavoro pianificato non viene eseguito con Background Task Inspector, consulta gli stati del lavoro elencati. Lo stato "In coda" indica che il lavoro è stato pianificato, ma è ancora in attesa di esecuzione.
Vantaggi:oltre a fornire un modo semplice per visualizzare tutte le attività, questo strumento è particolarmente utile se hai un lavoro a catena. Background Task Inspector offre una visualizzazione grafica che consente di visualizzare se l'errore di un'attività precedente potrebbe aver influito sull'esecuzione dell'attività successiva.
Visualizzazione elenco di Background Task Inspector
Visualizzazione del grafico di Background Task Inspector
adb shell dumpsys jobscheduler
Questo comando restituisce un elenco di tutti i job JobScheduler attivi (inclusi i worker WorkManager) insieme ai vincoli specificati e a quelli imposti dal sistema. Restituisce anche la cronologia dei job.
Utilizza questa opzione se vuoi un modo diverso per visualizzare il lavoro pianificato e i vincoli associati. Per le versioni di WorkManager precedenti alla 2.10.0, adb shell dumpsys jobscheduler restituirà un elenco di worker con questo nome:
[package name]/androidx.work.impl.background.systemjob.SystemJobService
Se la tua app ha più worker, l'aggiornamento a WorkManager 2.10.0 ti consentirà di visualizzare i nomi dei worker e distinguerli facilmente:
#WorkerName#@[package name]/androidx.work.impl.background.systemjob.SystemJobService
Vantaggi: questo comando è utile per capire se sono state imposte limitazioni a livello di sistema, che non puoi determinare con il Background Task Inspector. Ad esempio, verrà restituito il bucket di standby dell'app, che può influire sulla finestra in cui viene completato il lavoro pianificato.
Attiva logging di debug
Puoi attivare il logging personalizzato per visualizzare i log dettagliati di WorkManager, a cui verrà allegato WM—.
Vantaggi:ti consente di avere visibilità su quando viene pianificato il lavoro, vengono soddisfatti i vincoli e si verificano gli eventi del ciclo di vita. Puoi consultare questi log durante lo sviluppo dell'app.
WorkInfo.StopReason
Se noti un rendimento imprevedibile con un lavoratore specifico, puoi osservare a livello di programmazione il motivo per cui il lavoratore è stato interrotto nel precedente tentativo di esecuzione con WorkInfo.getStopReason.
È consigliabile configurare l'app in modo che osservi WorkInfo utilizzando getWorkInfoByIdFlow per identificare se il lavoro è interessato da limitazioni in background, vincoli, timeout frequenti o persino interrotto dall'utente.
Vantaggi:puoi utilizzare WorkInfo.StopReason per raccogliere dati sul campo relativi al rendimento dei tuoi lavoratori.
Debug della durata elevata del wakelock attribuita a WorkManager segnalata da Android vitals
Android vitals include una metrica dei wakelock parziali eccessivi, che evidenzia i wakelock che contribuiscono al consumo eccessivo della batteria. Potresti rimanere sorpreso nello scoprire che WorkManager acquisisce i wake lock per eseguire le attività e, se i wake lock superano la soglia impostata da Google Play, possono influire sulla visibilità della tua app. Come puoi eseguire il debug del motivo per cui la durata del wakelock è così elevata per il tuo lavoro? Puoi utilizzare i seguenti strumenti.
Dashboard Android vitals
Innanzitutto, verifica nel dashboard Android vitals per i wakelock eccessivi che la durata elevata del wakelock derivi da WorkManager e non da una sveglia o da un altro wakelock. Puoi utilizzare la documentazione Identificare i wakelock creati da altre API per capire quali wakelock vengono mantenuti a causa di WorkManager.
Perfetto
Perfetto è uno strumento per analizzare le tracce di sistema. Quando lo utilizzi per il debug specifico di WorkManager, puoi visualizzare la sezione "Stato dispositivo" per vedere quando è iniziato il lavoro, per quanto tempo è stato eseguito e in che modo contribuisce al consumo energetico.
Nella traccia "Stato dispositivo: job", puoi vedere tutti i worker eseguiti e i relativi wake lock.
Sezione Stato dispositivo in Perfetto, che mostra l'esecuzione di CleanupWorker e BlurWorker.
Risorse
Consulta la pagina Debug di WorkManager per una panoramica dei metodi di debug disponibili per altri scenari che potresti incontrare.
Per provare alcuni di questi metodi e scoprire di più sul debug di WorkManager, consulta il codelab WorkManager e test avanzati.
Passaggi successivi
Oggi abbiamo superato la riduzione del codice ed esplorato il modo in cui Android Runtime e Jetpack Compose eseguono il rendering dell'app. Che si tratti di precompilare i percorsi critici con i profili di base o di uniformare gli stati di scorrimento con le nuove funzionalità di Compose 1.9 e 1.10, questi strumenti si concentrano sull'esperienza della tua app. Inoltre, abbiamo approfondito le best practice per il debug del lavoro in background.
Chiedi ad Android
Venerdì ospiteremo una sessione AMA dal vivo sul rendimento. Poni subito le tue domande utilizzando l'hashtag #AskAndroid e ricevi risposte dagli esperti.
La sfida
Lunedì ti abbiamo invitato ad attivare R8. Oggi ti chiediamo di generare un profilo di baseline per la tua app.
Con Android Studio Otter, la procedura guidata del modulo Baseline Profile Generator rende questa operazione più semplice che mai. Scegli il Critical User Journey più importante, anche se si tratta solo dell'avvio e dell'accesso all'app, e genera un profilo.
Una volta ottenuto, esegui un Macrobenchmark per confrontare CompilationMode.None e CompilationMode.Partial.
Condividi i miglioramenti del tempo di avvio sui social media utilizzando l'hashtag #optimizationEnabled.
Sintonizzati domani
Hai ridotto le dimensioni dell'app con R8 e ottimizzato il runtime con l'ottimizzazione guidata dal profilo. Ma come fai a dimostrare questi successi ai tuoi stakeholder? E come fai a individuare le regressioni prima che raggiungano la produzione?
Unisciti a noi domani per il giorno 4: la guida al livellamento delle prestazioni, in cui illustreremo esattamente come misurare il tuo successo, dai dati sul campo in Play Vitals al tracciamento locale approfondito con Perfetto.
Continua a leggere
-
Istruzioni
Quando si lavora a nuove funzionalità, le prestazioni dell'app spesso passano in secondo piano. Tuttavia, anche se non è sempre la priorità degli sviluppatori, gli utenti possono vedere esattamente dove le prestazioni della tua app sono inferiori.
Ben Weiss • Lettura di 3 minuti
-
Istruzioni
Consapevole del fatto che il consumo eccessivo della batteria è una delle principali preoccupazioni degli utenti Android, Google ha adottato misure significative per aiutare gli sviluppatori a creare app più efficienti dal punto di vista energetico.
Alice Yuan • Lettura di 8 minuti
-
Istruzioni
Volevamo fornirti esempi di funzionalità basate sull'AI che utilizzano modelli sul dispositivo e sul cloud e ispirarti a creare esperienze piacevoli per i tuoi utenti.
Thomas Ezan, Ivy Knight • Lettura di 2 minuti
Segui gli aggiornamenti
Ricevi ogni settimana gli ultimi approfondimenti sullo sviluppo per Android direttamente nella tua casella di posta.