Panoramica della gestione della memoria

Il runtime Android (ART) e la macchina virtuale Dalvik utilizzano la paginazione e la mappatura della memoria (mmapping) per gestire la memoria. Ciò significa che qualsiasi memoria modificata da un'app, che si tratti di allocazione di nuovi oggetti o di accesso a pagine mappate, rimane residente nella RAM e non può essere espulsa dalla pagina. L'unico modo per liberare la memoria da un'app è rilasciare fa riferimento all'oggetto contenuto nell'app, rendendo la memoria disponibile garbage collector. C'è una sola eccezione: tutti i file mmappato senza modifiche, come codice, può essere scaricata dalla RAM se il sistema vuole usare altrove quella memoria.

Questa pagina spiega come Android gestisce i processi delle app e l'allocazione della memoria. Per saperne di più su come gestire la memoria in modo più efficiente nella tua app, vedi Gestisci la memoria dell'app.

Garbage collection

Un ambiente di memoria gestito, come la macchina virtuale ART o Dalvik, tiene traccia di ogni allocazione di memoria. Una volta determinato che una porzione di memoria non sia più usata dal programma, lo libera nell'heap, senza alcun intervento da parte del programmatore. Meccanismo per recuperare la memoria inutilizzata in un ambiente di memoria gestito è nota come garbage collection. Il garbage collection ha due obiettivi: trovare oggetti dati in un programma a cui non sarà possibile accedere in futuro; e recuperare le risorse utilizzate da questi oggetti.

L'heap di memoria di Android è generazionale, il che significa che diversi bucket di allocazioni monitorate, in base alla durata e alle dimensioni previste di un oggetto allocato. Ad esempio, gli oggetti allocati di recente appartengono alla generazione giovane. Quando un oggetto rimane attivo per un tempo sufficiente, può essere promosso a una generazione precedente, seguita da una generazione permanente.

Ogni generazione di heap ha il proprio limite superiore dedicato di memoria che gli oggetti possono occupare. Ogni volta che inizia una generazione il sistema esegue una garbage collection nel tentativo di liberare memoria. Durata della garbage collection dipende dalla generazione di oggetti che raccoglie e il numero di oggetti attivi in ogni generazione.

Anche se la garbage collection può essere piuttosto veloce, può influire sulle prestazioni della tua app. In genere non controlli quando si verifica un evento di garbage collection dall'interno del codice. Il sistema dispone di una serie di criteri per determinare quando eseguire garbage collection. Quando i criteri sono soddisfatti, il sistema interrompe l'esecuzione del processo e avvia la raccolta dei rifiuti. Se La garbage collection avviene nel mezzo di un loop di elaborazione intensivo come un'animazione o durante la riproduzione di musica, possono aumentare i tempi di elaborazione. Questo aumento può potenzialmente spingere l'esecuzione del codice nella tua app oltre la soglia consigliata di 16 ms per un rendering dei frame efficiente e fluido.

Inoltre, il flusso del codice può svolgere tipi di operazioni che forzano eventi di garbage collection o farli durare più a lungo del normale. Ad esempio, se assegni più oggetti nel tag la parte più interna di un for-loop durante ogni frame di un alpha unendo l'animazione, potresti inquinare la tua memoria con una molti oggetti. In questo caso, il garbage collector esegue più eventi di raccolta del garbage e può peggiorare le prestazioni dell'app.

Per informazioni più generali sulla garbage collection, consulta Raccolta dei rifiuti.

Condividere un ricordo

Per includere tutto ciò di cui ha bisogno nella RAM, Android cerca di condividere le pagine RAM tra i processi. it puoi farlo nei seguenti modi:

  • Ogni processo dell'app viene creato da un processo esistente chiamato Zygote. Il processo Zygote si avvia quando il sistema si avvia e carica il codice e le risorse del framework comuni (ad esempio i temi delle attività). Per avviare una nuova procedura per l'app: il sistema crea un fork del processo Zygote carica ed esegue il codice dell'app nel nuovo processo. Questo approccio consente alla maggior parte delle pagine RAM allocate, e le risorse del framework da usare in tutti i processi dell'app.
  • La maggior parte dei dati statici viene inserita in un processo. Questa tecnica consente di condividere i dati tra i processi e di paginarli se necessario. Ecco alcuni esempi di dati statici: codice Dalvik (inserendoli in un file .odex prelinkato per l'allocazione diretta in memoria), risorse dell'app (progettando la tabella delle risorse in modo che sia una struttura che può essere allocata in memoria e allineando le voci zip dell'APK) ed elementi di progetto tradizionali come il codice nativo nei file .so.
  • In molti casi, Android condivide la stessa RAM dinamica tra i processi utilizzando regioni di memoria condivisa allocate in modo esplicito (con ashmem o gralloc). Ad esempio, le aree delle finestre utilizzano la memoria condivisa tra l'app e il compositore dello schermo, mentre i buffer del cursore utilizzano la memoria condivisa tra il fornitore di contenuti e il client.

A causa dell'ampio uso della memoria condivisa, determinare la quantità di memoria utilizzata dalla tua app richiede cura. Tecniche per determinare correttamente la dell'uso della memoria sono trattati nel Analisi dell'utilizzo della RAM.

Alloca e recupera memoria dell'app

Il cumulo di Dalvik è vincolato a un un singolo intervallo di memoria virtuale per ogni processo dell'app. Questo definisce la dimensione logica dell'heap, che può aumentare in base alle esigenze ma solo entro un limite definito dal sistema per ogni app.

Le dimensioni logiche dell'heap non corrispondono a la quantità di memoria fisica utilizzata dall'heap. Durante l'ispezione dell'heap della tua app, Android calcola un valore chiamato Proportional Set Size (PSS), che tiene conto sia delle pagine sporche che pulite condivisi con altri processi, ma solo in un proporzionale al numero di app che condividono quella RAM. Il totale (PSS) è l'aspetto che il sistema sia la tua memoria fisica. Per ulteriori informazioni sui PSS, consulta Analisi dell'utilizzo della RAM guida.

L'heap di Dalvik non compatta la logica dimensioni dell'heap, il che significa che Android deframmentare l'heap per chiudere lo spazio. Android può ridurre le dimensioni logiche dell'heap solo quando spazio inutilizzato alla fine dell'heap. Tuttavia, il sistema può comunque ridurre la memoria fisica usata dall'heap. Dopo la garbage collection, Dalvik percorre l'heap e trova le pagine inutilizzate, poi restituisce quelle pagine al kernel usando madvise. Quindi, accoppiato allocazioni e deal di attività i blocchi dovrebbero comportare la rivendicazione di tutti (o quasi) la memoria fisica utilizzata. Tuttavia, recuperare la memoria da allocazioni ridotte può essere è meno efficiente perché la pagina utilizzava per una piccola allocazione possono essere qualcos'altro che non è stato ancora liberato.

Limita memoria app

Per mantenere un ambiente multi-tasking funzionale, Android imposta un limite massimo per le dimensioni dell'heap per ogni app. Il limite esatto delle dimensioni dell'heap varia da un dispositivo all'altro in base alla quantità di RAM complessivamente disponibile. Se la tua app ha raggiunto della capacità heap e prova ad allocarne memoria, può ricevere un OutOfMemoryError.

In alcuni casi, potresti voler eseguire una query per determinare esattamente quanto spazio heap disponibili sul dispositivo corrente, ad esempio per determinare la quantità di dati sicura da conservare . Puoi eseguire una query sul sistema per questa cifra richiamando getMemoryClass(). Questo metodo restituisce un numero intero che indica il numero di disponibili per l'heap dell'app.

Cambio di app

Quando gli utenti passano da un'app all'altra, Android mantiene le app non sono in primo piano, ovvero non sono visibili all'utente o stanno eseguendo servizi in primo piano come la riproduzione di musica: in una cache. Ad esempio, quando un utente avvia un'app per la prima volta, viene creato un processo; ma quando l'utente esce dall'app, la procedura non viene chiusa. Il sistema conserva il processo nella cache. Se l'utente torna all'app in un secondo momento, il sistema riutilizza il processo, velocizzando il passaggio da un'app all'altra.

Se la tua app dispone di un processo nella cache e conserva le risorse di cui attualmente non ha bisogno, l'app, anche quando l'utente non la usa, influisce sulla capacità del sistema il rendimento complessivo. Quando le risorse del sistema, come la memoria, si esauriscono, vengono terminati i processi nella cache. Inoltre, il sistema prende in considerazione i processi che contengono la maggior parte e può terminarle per liberare RAM.

Nota: minore è il consumo di memoria da parte dell'app quando si trova nella cache, maggiori sono le probabilità di non essere ucciso e di poter riprendere rapidamente. Tuttavia, a seconda dei requisiti di sistema istantanei, è possibile che la cache e i processi vengono terminati in qualsiasi momento, a prescindere dall'utilizzo delle risorse.

Per ulteriori informazioni su come i processi vengono memorizzati nella cache non vengono eseguiti in primo piano e come È Android a decidere quali possono essere uccisi, Processi e thread guida.

Test di stress della memoria

Sebbene i problemi di stress della memoria siano meno comuni sui dispositivi di fascia alta, possono comunque causare problemi per gli utenti che utilizzano dispositivi con poca RAM, ad esempio quelli con Android (versione Go). È importante provare a riprodurre questo ambiente con stress di memoria in modo da poter scrivere test di strumentazione per verificare l'app e migliorare l'esperienza degli utenti che usano dispositivi con memoria ridotta.

Test di applicazione stressante

Stressful Application Test (stressapptest) [Test delle applicazioni stressanti] è un test dell'interfaccia di memoria che aiuta a creare situazioni realistiche e con un carico elevato per testare vari tipi di memoria e limitazioni hardware per la tua app. Grazie alla capacità di definire limiti di tempo e memoria, consente di scrivere la strumentazione per verificare incontri nel mondo reale di situazioni con memoria elevata. Ad esempio, utilizza la seguente serie di comandi per eseguire il push della libreria statica nel tuo file system di dati: rendilo eseguibile ed esegui un test di stress per 20 secondi di 990 MB:
    adb push stressapptest /data/local/tmp/
    adb shell chmod 777 /data/local/tmp/stressapptest
    adb shell /data/local/tmp/stressapptest -s 20 -M 990

  

Consulta la stressapptest documentazione per ulteriori informazioni sull'installazione dello strumento, argomenti comuni e gestione degli errori informazioni.

Osservazioni su stressapptest

Strumenti come stressapptest possono essere utilizzati per richiedere allocazioni di memoria superiori a quelle disponibili gratuitamente. Questo tipo di richiesta può generare vari avvisi di cui dovresti essere a conoscenza nel dal lato dello sviluppo. Tre avvisi principali che possono essere generati a causa di una scarsa disponibilità di memoria includono:
  • SIGABRT: si tratta di un arresto anomalo nativo fatale per il processo a causa della richiesta di allocazioni di dimensioni superiori alla memoria libera, mentre il sistema è già sotto pressione di memoria.
  • SIGQUIT: Genera un dump della memoria di base e termina il processo quando viene rilevato dal test di strumentazione.
  • TRIM_MEMORY_EVENTS: Questi callback sono disponibili su Android 4.1 (livello API 16) e versioni successive e forniscono di memoria per il processo.