Registra allocazioni Java/Kotlin

La registrazione delle allocazioni Java/Kotlin ti aiuta a identificare pattern di memoria indesiderati che potrebbero causare problemi di rendimento. Il profiler può mostrarti quanto segue sulle allocazioni di oggetti:

  • Quali tipi di oggetti sono stati allocati e quanto spazio utilizzano.
  • Lo stack trace di ogni allocazione, incluso il thread in cui è stata eseguita.
  • Quando gli oggetti sono stati deallocati.

Devi registrare le allocazioni di memoria durante l'interazione normale ed estrema degli utenti per identificare esattamente dove il codice alloca troppi oggetti in un breve periodo di tempo o alloca oggetti che vengono persi. Scopri di più sul perché dovresti profilare la memoria della tua app.

Come registrare le allocazioni Java/Kotlin

Per registrare le allocazioni Java/Kotlin, seleziona l'attività Monitora consumo di memoria (allocazioni Java/Kotlin) dalla scheda Home del profiler. Tieni presente che per registrare le allocazioni Java/Kotlin devi disporre di un'app di cui è possibile eseguire il debug (utilizza Profiler: run 'app' as debuggable (complete data)).

Android Studio acquisisce tutte le allocazioni di oggetti in memoria per impostazione predefinita. Se hai un'app che alloca molti oggetti, potresti notare rallentamenti visibili nell'app durante la profilazione. Per migliorare le prestazioni durante la profilazione, vai al menu a discesa Monitoraggio allocazione e seleziona Campionato anziché Completo. Durante il campionamento, il profiler raccoglie le allocazioni di oggetti in memoria a intervalli regolari.

Per forzare un evento di garbage collection durante la registrazione, fai clic sull'icona del cestino .

Panoramica delle allocazioni Java/Kotlin

Dopo aver interrotto la registrazione, vedrai quanto segue:

  • La cronologia degli eventi mostra gli stati di attività, gli eventi di input utente e gli eventi di rotazione dello schermo.
  • La cronologia dell'utilizzo della memoria mostra le seguenti informazioni. Seleziona una parte della cronologia per filtrare un determinato intervallo di tempo.
    • Un grafico a barre in pila che mostra la quantità di memoria utilizzata da ogni categoria di memoria, come indicato dall'asse Y a sinistra e dalla legenda dei colori in alto.
    • Una linea tratteggiata indica il numero di oggetti allocati, come indicato dall'asse Y a destra.
    • Un'icona per ogni evento di garbage collection.
  • La scheda Tabella mostra un elenco di classi. Il Conteggio totale è il numero di allocazioni alla fine dell'intervallo di tempo selezionato (Allocazioni meno Deallocazioni), quindi potrebbe essere utile eseguire il debug delle classi che hanno i valori di Conteggio totale più alti. Se ti interessa di più risolvere i problemi relativi ai corsi in base alle allocazioni di picco nell'intervallo di tempo selezionato, dai la priorità in base alle allocazioni. Analogamente, le Dimensioni rimanenti sono le Dimensioni allocazioni meno le Dimensioni deallocazioni in byte.
  • Quando fai clic su una classe nell'elenco Tabella, si apre il riquadro Istanza con un elenco di oggetti associati, tra cui quando sono stati allocati, quando sono stati deallocati e le relative dimensioni superficiali.
  • La scheda Visualizzazione mostra una visualizzazione aggregata di tutti gli oggetti nello stack di chiamate durante l'intervallo di tempo selezionato. Mostra essenzialmente la quantità di memoria totale occupata dallo stack di chiamate con le istanze mostrate. La prima riga mostra il nome del thread. Per impostazione predefinita, gli oggetti sono impilati da sinistra a destra in base alle dimensioni dell'allocazione; utilizza il menu a discesa per modificare l'ordinamento.

  • Utilizza il menu a discesa del segmento per filtrare in base a determinati segmenti. Oltre ai filtri disponibili quando acquisisci un dump dell'heap, puoi filtrare le classi nell'heap JNI, l'heap che mostra dove vengono allocate e rilasciate le referenze Java Native Interface (JNI).

  • Utilizza il menu a discesa Disposizione per scegliere come disporre le allocazioni. Oltre alle disposizioni disponibili quando acquisisci un dump dell'heap, puoi disporre per callstack.

Come viene conteggiata la memoria

I numeri visualizzati nella parte superiore si basano su tutte le pagine di memoria privata di cui è stato eseguito il commit della tua app, secondo il sistema Android. Questo conteggio non include le pagine condivise con il sistema o altre app. Le categorie nel conteggio della memoria sono le seguenti:

  • Java: memoria degli oggetti allocati dal codice Java o Kotlin.
  • Nativa: memoria degli oggetti allocati dal codice C o C++.

    Anche se non utilizzi C++ nella tua app, potresti notare una certa quantità di memoria nativa utilizzata qui perché il framework Android utilizza la memoria nativa per gestire varie attività per tuo conto, ad esempio quando gestisce asset immagine e altre grafiche, anche se il codice che hai scritto è in Java o Kotlin.

  • Grafica: memoria utilizzata per le code del buffer della grafica per visualizzare i pixel sullo schermo, incluse superfici GL, texture GL e altro ancora. Tieni presente che si tratta di memoria condivisa con la CPU, non di memoria GPU dedicata.

  • Stack: memoria utilizzata dagli stack nativi e Java nella tua app. Questo valore di solito si riferisce al numero di thread in esecuzione nella tua app.

  • Codice: memoria utilizzata dall'app per codice e risorse, ad esempio bytecode DEX, codice DEX ottimizzato o compilato.so e caratteri.

  • Altro: memoria utilizzata dalla tua app che il sistema non sa come categorizzare.

  • Allocati: il numero di oggetti Java/Kotlin allocati dalla tua app. Questo non include gli oggetti allocati in C o C++.

Ispeziona il record di allocazione

Per esaminare il record di allocazione:

  1. Sfoglia l'elenco delle classi nella scheda Tabella per trovare oggetti con valori di Allocazioni o Conteggio totale insolitamente elevati (a seconda di ciò per cui stai eseguendo l'ottimizzazione) e che potrebbero essere soggetti a perdite.
  2. Nel riquadro Visualizzazione istanza, fai clic su un'istanza. A seconda di ciò che si applica a quell'istanza, si apre la scheda Campi o Stack di chiamate di allocazione. Utilizza le informazioni nelle schede Campi o Stack di chiamate di allocazione per determinare se le istanze sono effettivamente necessarie o duplicazioni non necessarie.

Fai clic con il tasto destro del mouse su una voce dell'elenco per passare al codice sorgente pertinente.

Visualizza i riferimenti JNI globali

Java Native Interface (JNI) è un framework che consente al codice Java e al codice nativo di chiamarsi a vicenda. I riferimenti JNI vengono gestiti manualmente dal codice nativo, quindi possono verificarsi problemi, tra cui:

  • Gli oggetti Java utilizzati dal codice nativo vengono mantenuti attivi troppo a lungo.
  • Alcuni oggetti nell'heap Java potrebbero diventare irraggiungibili se un riferimento JNI viene eliminato senza essere prima eliminato esplicitamente.
  • Il limite di riferimento JNI globale è esaurito.

Per risolvere questi problemi, seleziona Visualizza heap JNI nel profiler per sfogliare tutti i riferimenti JNI globali e filtrarli per tipi Java e stack di chiamate native. Fai clic con il tasto destro del mouse su un campo dell'istanza nella scheda Campi e seleziona Vai a istanza per visualizzare lo stack di chiamate di allocazione pertinente.

La scheda Allocation Call Stack mostra dove vengono allocate e rilasciate le referenze JNI nel codice.

Per saperne di più su JNI, consulta Suggerimenti per JNI.