La piattaforma Android funziona sulla premessa che la memoria libera sia memoria sprecata. Tenta di utilizzare sempre tutta la memoria disponibile. Ad esempio, il sistema mantiene le app in memoria dopo che sono state chiuse in modo che l'utente possa tornare rapidamente a utilizzarle. Per questo motivo, i dispositivi Android spesso funzionano con pochissima memoria libera. La gestione della memoria è fondamentale per allocare correttamente la memoria tra i processi di sistema importanti e molte applicazioni utente.
Questa pagina illustra le nozioni di base su come Android alloca la memoria per il sistema e per le applicazioni utente. Spiega inoltre come il sistema operativo reagisce alle situazioni di bassa memoria.
Tipi di memoria
I dispositivi Android contengono tre diversi tipi di memoria: RAM, zRAM e spazio di archiviazione. Tieni presente che sia la CPU che la GPU accedono alla stessa RAM.
Figura 1. Tipi di memoria: RAM, zRAM e spazio di archiviazione
La RAM è il tipo di memoria più veloce, ma in genere ha dimensioni limitate. I dispositivi di fascia alta in genere dispongono della maggiore quantità di RAM.
zRAM è una partizione della RAM utilizzata per lo spazio di scambio. Tutto viene compresso quando viene inserito nella zRAM e poi decompreso quando viene copiato fuori dalla zRAM. Le dimensioni di questa parte di RAM aumentano o diminuiscono man mano che le pagine vengono spostate in zRAM o rimosse da essa. I produttori di dispositivi possono impostare le dimensioni massime.
Lo spazio di archiviazione contiene tutti i dati permanenti, come il file system e il codice oggetto incluso per tutte le app, le librerie e la piattaforma. Lo spazio di archiviazione ha una capacità molto maggiore rispetto agli altri due tipi di memoria. Su Android, lo spazio di archiviazione non viene utilizzato per lo spazio di scambio come in altre implementazioni di Linux poiché le scritture frequenti possono causare l'usura di questa memoria e ridurre la durata del medium di archiviazione.
Pagine di memoria
La RAM è suddivisa in pagine. In genere, ogni pagina occupa 4 KB di memoria.
Le pagine sono considerate libere o utilizzate. Le pagine libere sono RAM non utilizzata. Le pagine utilizzate sono la RAM utilizzata attivamente dal sistema e sono raggruppate nelle seguenti categorie:
- Memorizzata nella cache: memoria basata su un file nello spazio di archiviazione (ad esempio codice o file con mappatura in memoria). Esistono due tipi di memoria nella cache:
- Privato: di proprietà di un processo e non condiviso
- Pulito: copia non modificata di un file nello spazio di archiviazione, può essere eliminata da
kswapd
per aumentare la memoria libera - Sporco: copia modificata del file nello spazio di archiviazione; può essere spostata o compressa nella zRAM da
kswapd
per aumentare la memoria libera
- Pulito: copia non modificata di un file nello spazio di archiviazione, può essere eliminata da
- Condiviso: utilizzato da più processi
- Pulita: copia non modificata del file nello spazio di archiviazione, può essere eliminata da
kswapd
per aumentare la memoria libera - Sporco: copia modificata del file nello spazio di archiviazione. Consente di scrivere nuovamente le modifiche nel file nello spazio di archiviazione per aumentare la memoria libera di
kswapd
o utilizzando esplicitamentemsync()
omunmap()
.
- Pulita: copia non modificata del file nello spazio di archiviazione, può essere eliminata da
- Privato: di proprietà di un processo e non condiviso
- Anonimo: memoria non basata su un file nello spazio di archiviazione (ad esempio, allocata da
mmap()
con il flagMAP_ANONYMOUS
impostato)- Sporca: può essere spostata/compressa in zRAM da
kswapd
per aumentare la memoria libera
- Sporca: può essere spostata/compressa in zRAM da
Le proporzioni di pagine libere e utilizzate variano nel tempo man mano che il sistema gestisce attivamente la RAM. I concetti introdotti in questa sezione sono fondamentali per gestire le situazioni di scarsa memoria. La sezione successiva di questo documento le illustra in maggiore dettaglio.
Gestione della memoria ridotta
Android dispone di due meccanismi principali per gestire le situazioni di scarsa memoria: il kernel swap daemon e il low-memory killer.
Daemon di scambio del kernel
Il kernel swap daemon (kswapd
) fa parte del kernel Linux e converte la memoria utilizzata in memoria libera. Il daemon diventa attivo quando la memoria libera sul
dispositivo è in esaurimento. Il kernel Linux gestisce soglie di memoria libera bassa e alta.
Quando la memoria libera scende al di sotto della soglia minima, kswapd
inizia a recuperare la memoria. Quando la memoria libera raggiunge la soglia alta, kswapd
interrompe il recupero della memoria.
kswapd
può recuperare le pagine pulite eliminandole perché sono supportate dall'archiviazione e non sono state modificate. Se un processo tenta di accedere a una pagina pulita che è stata eliminata, il sistema la copia dallo spazio di archiviazione alla RAM. Questa
operazione è nota come paginazione a richiesta.
Figura 2. Pagina libera, supportata da spazio di archiviazione, eliminata
kswapd
può spostare le pagine sporche private memorizzate nella cache e le pagine sporche anonime nella zRAM, dove vengono compresse. In questo modo viene liberata la memoria disponibile nella RAM (pagine libere). Se un processo tenta di toccare una pagina sporca in zRAM, la pagina viene decompressa e spostata di nuovo nella RAM. Se il processo associato a una pagina compressa viene interrotto, la pagina viene eliminata dalla zRAM.
Se la quantità di memoria libera scende al di sotto di una determinata soglia, il sistema inizia a uccidere i processi.
Figura 3. Pagina sporca spostata in zRAM e compressa
Killer a bassa memoria
Spesso kswapd
non riesce a liberare memoria sufficiente per il sistema. In questo caso, il sistema utilizza onTrimMemory()
per notificare a un'app che la memoria è in esaurimento e che deve ridurre le allocazioni. Se ciò non è sufficiente, il kernel inizia ad arrestare i processi per liberare memoria. Per farlo, utilizza l'utilità LMK (Low-Memory Killer).
Per decidere quale processo terminare, LMK utilizza un punteggio "out of memory" chiamato
oom_adj_score
per dare la priorità ai processi in esecuzione. I processi con un punteggio elevato vengono terminati pirma. Le app in background sono le prime a essere interrotte e i processi di sistema sono gli ultimi. La tabella seguente elenca le categorie di punteggio LMK dal più alto al più basso. Gli elementi della categoria con il punteggio più alto, nella prima riga, verranno eliminati per primi:
Figura 4. Processi Android, con punteggi elevati in alto e punteggi bassi in basso
Di seguito sono riportate le descrizioni delle varie categorie nella tabella precedente:
App in background: app che sono state eseguite in precedenza e che al momento non sono attive. LMK chiuderà prima le app in background, a partire da quella con il valore
oom_adj_score
più elevato.App precedente: l'app in background utilizzata più di recente. L'app precedente ha una priorità più alta (un punteggio più basso) rispetto alle app in background perché è più probabile che l'utente passi a questa app rispetto a una delle app in background.
App Home: si tratta dell'app Avvio app. Se la chiudi, lo sfondo desaparece.
Servizi: i servizi vengono avviati dalle applicazioni e possono includere la sincronizzazione o il caricamento sul cloud.
App percepibili: app non in primo piano che sono percepibili dall'utente in qualche modo, ad esempio l'esecuzione di una procedura di ricerca che mostra una piccola interfaccia utente o l'ascolto di musica.
App in primo piano: l'app attualmente in uso. L'interruzione dell'app in primo piano sembra un arresto anomalo dell'applicazione che potrebbe indicare all'utente che qualcosa non va nel dispositivo.
Persistenti (servizi): si tratta di servizi di base per il dispositivo, come la telefonia e il Wi-Fi.
Sistema: processi di sistema. Quando questi processi vengono interrotti, lo smartphone potrebbe sembrare riavviato.
Nativo: processi di basso livello utilizzati dal sistema (ad esempio
kswapd
).
I produttori di dispositivi possono modificare il comportamento di LMK.
Calcolo dell'impronta della memoria
Il kernel tiene traccia di tutte le pagine di memoria del sistema.
Figura 5. Pagine utilizzate da processi diversi
Quando determina la quantità di memoria utilizzata da un'app, il sistema deve tenere conto delle pagine condivise. Le app che accedono allo stesso servizio o alla stessa raccolta condivideranno le pagine di memoria. Ad esempio, Google Play Services e un'app di gioco potrebbero condividere un servizio di geolocalizzazione. Di conseguenza, è difficile determinare quanta memoria appartiene al servizio in generale rispetto a ogni applicazione.
Figura 6. Pagine condivise da due app (al centro)
Per determinare l'impronta in memoria di un'applicazione, è possibile utilizzare una delle seguenti metriche:
- Resident Set Size (RSS): il numero di pagine condivise e non condivise utilizzate dall'app
- Dimensione set proporzionale (PSS): il numero di pagine non condivise utilizzate dall'app e una distribuzione uniforme delle pagine condivise (ad esempio, se tre processi condividono 3 MB, ogni processo riceve 1 MB in PSS)
- Dimensioni dell'insieme unico (USS): il numero di pagine non condivise utilizzate dall'app (le pagine condivise non sono incluse)
Il PSS è utile per il sistema operativo quando vuole sapere quanta memoria viene utilizzata da tutte le procedure, poiché le pagine non vengono conteggiate più volte. Il calcolo del PSS richiede molto tempo perché il sistema deve determinare quali pagine sono condivise e da quanti processi. RSS non fa distinzione tra pagine condivise e non condivise (il calcolo è più rapido) ed è più adatto per monitorare le modifiche all'allocazione della memoria.
Risorse aggiuntive
- Panoramica della gestione della memoria
- Processi e ciclo di vita delle applicazioni
- Informazioni sull'utilizzo della memoria di Android - Presentazione Google I/O
- Memoria e giochi Android - Presentazione Google I/O
- Daemon di eliminazione per scarsa memoria di Android
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Tempi di avvio dell'app