Il processo del daemon di terminazione per memoria insufficiente di Android (lmkd
) monitora lo stato della memoria di un sistema Android in esecuzione e reagisce all'elevata pressione sulla memoria terminando i processi meno essenziali per mantenere le prestazioni del sistema a livelli accettabili.
Informazioni sulla pressione della memoria
Un sistema Android che esegue più processi in parallelo potrebbe riscontrare situazioni in cui la memoria di sistema è esaurita e i processi che richiedono più memoria subiscono ritardi notevoli. La pressione della memoria, uno stato in cui il sistema ha poca memoria, richiede ad Android di liberare memoria (per alleviare la pressione) limitando o terminando i processi non importanti, richiedendo ai processi di liberare risorse non critiche memorizzate nella cache e così via.
In passato, Android monitorava la pressione della memoria di sistema utilizzando un driver
LMK (Low Memory Killer) nel kernel, un meccanismo rigido che dipende da valori
hardcoded. A partire dal kernel 4.12, il driver LMK viene rimosso dal kernel upstream e lo spazio utente lmkd
esegue il monitoraggio della memoria e le attività di terminazione dei processi.
Informazioni sullo stallo di pressione
Android 10 e versioni successive supportano una nuova modalità lmkd
che
utilizza i monitor PSI (kernel pressure stall information) per il rilevamento della pressione della memoria. Il patchset PSI nel kernel upstream (portato alle versioni precedenti dei kernel 4.9 e 4.14)
misura il tempo di ritardo delle attività a causa di
carenze di memoria. Poiché questi ritardi influiscono direttamente sull'esperienza utente, rappresentano una metrica conveniente per determinare la gravità della pressione sulla memoria. Il
kernel upstream include anche monitor PSI che consentono ai processi di spazio utente con privilegi (come lmkd
) di specificare le soglie per questi ritardi e di
iscriversi agli eventi del kernel quando una soglia viene superata.
Indicatori PSI e indicatori vmpressure
Poiché i segnali vmpressure
(generati dal kernel per il rilevamento della pressione della memoria e utilizzati da lmkd
) spesso includono numerosi falsi positivi, lmkd
deve eseguire il filtraggio per determinare se la memoria è effettivamente sotto pressione.
Ciò comporta lmkd
riattivazioni non necessarie e l'utilizzo di risorse
di calcolo aggiuntive. L'utilizzo del monitoraggio PSI consente di rilevare con maggiore precisione la pressione della memoria e riduce al minimo l'overhead di filtraggio.
Utilizzare i monitor PSI
Per utilizzare i monitor PSI anziché gli eventi vmpressure
, configura la proprietà ro.lmk.use_psi
. Il valore predefinito è true
, il che rende PSI il meccanismo predefinito di rilevamento della pressione della memoria per lmkd
. Poiché i monitor PSI richiedono il supporto del kernel, quest'ultimo deve includere le patch di backporting PSI ed essere compilato con il supporto PSI abilitato (CONFIG_PSI=y
).
Svantaggi del driver LMK in-kernel
Android ritira il driver LMK a causa di una serie di problemi, tra cui:
- I dispositivi con poca RAM dovevano essere ottimizzati in modo aggressivo e anche in questo caso le prestazioni erano scarse nei carichi di lavoro con una pagecache attiva di grandi dimensioni basata su file. Le scarse prestazioni hanno portato a un thrashing e a nessuna uccisione.
- Il driver del kernel LMK si basava sui limiti di memoria libera, senza scalabilità in base alla pressione della memoria.
- A causa della rigidità del design, i partner spesso personalizzavano il driver in modo che funzionasse sui loro dispositivi.
- Il driver LMK si è agganciato all'API slab shrinker, che non era
progettata per operazioni pesanti come la ricerca di target e la loro eliminazione, il che ha rallentato il processo
vmscan
.
Userspace lmkd
Lo spazio utente lmkd
implementa la stessa funzionalità del driver in-kernel,
ma utilizza i meccanismi del kernel esistenti per rilevare e stimare la pressione della memoria. Questi
meccanismi includono l'utilizzo di eventi vmpressure
generati dal kernel o di monitor PSI (Pressure Stall Information) per ricevere notifiche sui livelli di pressione della memoria e l'utilizzo delle funzionalità cgroup della memoria per limitare le risorse di memoria allocate a ogni processo in base alla sua importanza.
Utilizzare userspace lmkd in Android 10
In Android 9 e versioni successive, lo spazio utente lmkd
si attiva se
non viene rilevato un driver LMK in-kernel. Poiché lo spazio utente lmkd
richiede il supporto del kernel per i cgroup di memoria, il kernel deve essere compilato con le
seguenti impostazioni di configurazione:
CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
Elimina strategie
Userspace lmkd
supporta strategie di interruzione basate su eventi vmpressure
o monitor PSI, sulla loro gravità e su altri suggerimenti, ad esempio l'utilizzo dello spazio di swap. Le strategie di chiusura
variano a seconda che si tratti di dispositivi con poca memoria o ad alte prestazioni:
- Sui dispositivi con poca memoria, il sistema deve tollerare una pressione della memoria maggiore come modalità di funzionamento normale.
- Sui dispositivi ad alte prestazioni, l'utilizzo della memoria deve essere considerato una situazione anomala e risolta prima che influisca sulle prestazioni complessive.
Puoi configurare la strategia di interruzione utilizzando la proprietà ro.config.low_ram
.
Lo spazio utente lmkd
supporta anche una modalità legacy in cui prende decisioni di chiusura
utilizzando le stesse strategie del driver LMK in-kernel (ovvero soglie di memoria
libera e cache dei file). Per attivare la modalità legacy, imposta la proprietà
ro.lmk.use_minfree_levels
su true
.
Configura lmkd
Configura lmkd
per un dispositivo specifico utilizzando le seguenti proprietà.
Proprietà | Usa | Predefinito |
---|---|---|
ro.config.low_ram
|
Specifica se il dispositivo è a bassa RAM o ad alte prestazioni. | false
|
ro.lmk.use_psi |
Utilizza i monitor PSI (anziché gli eventi vmpressure ). |
true |
ro.lmk.use_minfree_levels
|
Utilizza le soglie di memoria libera e cache dei file per prendere decisioni di interruzione dei processi (ovvero, corrisponde alla funzionalità del driver LMK in-kernel). | false
|
ro.lmk.low
|
Il punteggio minimo di oom_adj per i processi idonei all'interruzione al livello vmpressure basso.
|
1001 (disattivato) |
ro.lmk.medium
|
Il punteggio minimo oom_adj per i processi idonei a essere
terminati al livello medio vmpressure .
|
800 (servizi memorizzati nella cache o non essenziali) |
ro.lmk.critical
|
Il punteggio minimo oom_adj per i processi idonei all'interruzione a livello critico vmpressure .
|
0 (qualsiasi processo) |
ro.lmk.critical_upgrade
|
Abilita l'upgrade al livello critico. | false
|
ro.lmk.upgrade_pressure
|
Il valore massimo di mem_pressure al quale viene eseguito l'upgrade del livello
perché il sistema esegue troppi scambi.
|
100 (disattivato) |
ro.lmk.downgrade_pressure
|
Il valore minimo di mem_pressure in corrispondenza del quale un evento vmpressure
viene ignorato perché è ancora disponibile memoria libera sufficiente.
|
100 (disattivato) |
ro.lmk.kill_heaviest_task
|
Termina l'attività idonea più pesante (decisione migliore) anziché un'attività idonea qualsiasi (decisione rapida). | false
|
ro.lmk.kill_timeout_ms
|
Durata in millisecondi dopo un'interruzione quando non verrà eseguita un'ulteriore interruzione. | 0 (disattivato) |
ro.lmk.debug
|
Attiva i log di debug di lmkd .
|
false
|
Configurazione del dispositivo di esempio:
PRODUCT_PROPERTY_OVERRIDES += \
ro.lmk.low=1001 \
ro.lmk.medium=800 \
ro.lmk.critical=0 \
ro.lmk.critical_upgrade=false \
ro.lmk.upgrade_pressure=100 \
ro.lmk.downgrade_pressure=100 \
ro.lmk.kill_heaviest_task=true
lmkd userspace in Android 11
Android 11 migliora la lmkd
introducendo una nuova
strategia di chiusura. La strategia di interruzione utilizza un meccanismo PSI per il rilevamento della pressione della memoria
introdotto in Android 10. lmkd
in
Android 11 tiene conto dei livelli di utilizzo delle risorse di memoria
e del thrashing per evitare l'esaurimento della memoria e il peggioramento delle prestazioni.
Questa strategia di chiusura sostituisce le precedenti e può essere utilizzata sia su dispositivi ad alte prestazioni sia su dispositivi con poca RAM (Android Go).
Requisiti del kernel
Per i dispositivi Android 11, lmkd
richiede le seguenti funzionalità del kernel:
- Includi le patch PSI e abilita PSI (backport disponibili nei kernel comuni Android 4.9, 4.14 e 4.19).
- Includi patch di supporto PIDFD (backport disponibili nei kernel comuni di Android 4.9, 4.14 e 4.19).
- Per i dispositivi con poca RAM, includi i cgroup di memoria.
Il kernel deve essere compilato con le seguenti impostazioni di configurazione:
CONFIG_PSI=y
Configurare lmkd in Android 11
La strategia di eliminazione della memoria in Android 11 supporta i parametri di ottimizzazione e i valori predefiniti elencati di seguito. Queste funzionalità sono disponibili sia su dispositivi ad alte prestazioni che su quelli con poca RAM.
Proprietà | Usa | Predefinito | |
---|---|---|---|
Prestazioni elevate | RAM insufficiente | ||
ro.lmk.psi_partial_stall_ms |
La soglia di stallo PSI parziale, in millisecondi, per l'attivazione della notifica di memoria insufficiente. Se il dispositivo riceve notifiche di pressione della memoria troppo tardi, diminuisci questo valore per attivare notifiche precedenti. Se le notifiche di pressione della memoria vengono attivate inutilmente, aumenta questo valore per rendere il dispositivo meno sensibile al rumore. | 70 |
200 |
ro.lmk.psi_complete_stall_ms |
La soglia di stallo PSI completa, in millisecondi, per l'attivazione delle notifiche di memoria critiche. Se il dispositivo riceve notifiche di pressione critica della memoria troppo tardi, diminuisci questo valore per attivare notifiche precedenti. Se le notifiche relative alla pressione della memoria critica vengono attivate inutilmente, aumenta questo valore per rendere il dispositivo meno sensibile al rumore. | 700 |
|
ro.lmk.thrashing_limit |
La quantità massima di errori di working set come percentuale della dimensione totale della cache di pagine basata su file. I refault del working set superiori a questo valore indicano che il sistema sta eseguendo il thrashing della cache delle pagine. Se le prestazioni del dispositivo sono influenzate durante la pressione sulla memoria, diminuisci il valore per limitare l'attività di thrashing. Se le prestazioni del dispositivo vengono interrotte inutilmente per motivi di thrashing, aumenta il valore per consentire un thrashing maggiore. | 100 |
30 |
ro.lmk.thrashing_limit_decay |
Il decadimento della soglia di thrashing espresso come percentuale della soglia originale utilizzata per abbassare la soglia quando il sistema non recupera, anche dopo un'interruzione. Se il thrashing continuo produce interruzioni non necessarie, diminuisci il valore. Se la risposta al thrashing continuo dopo un'interruzione è troppo lenta, aumenta il valore. | 10 |
50 |
ro.lmk.swap_util_max |
La quantità massima di memoria scambiata come percentuale della memoria scambiabile totale. Quando la memoria di swap supera questo limite, significa che il
sistema ha scambiato la maggior parte della memoria scambiabile ed è ancora sotto pressione.
Ciò può accadere quando le allocazioni non scambiabili generano una pressione sulla memoria che non può essere alleviata dallo scambio perché la maggior parte della memoria scambiabile è già stata scambiata. Il valore predefinito è 100, il che disattiva
questo controllo. Se le prestazioni del dispositivo sono interessate dalla
pressione della memoria mentre l'utilizzo dello spazio di swap è elevato e il livello di swap libero
non scende a ro.lmk.swap_free_low_percentage , diminuisci
il valore per limitare l'utilizzo dello spazio di swap. |
100 |
100 |
Anche i seguenti vecchi parametri di ottimizzazione funzionano con la nuova strategia di eliminazione.
Proprietà | Usa | Predefinito | |
---|---|---|---|
Prestazioni elevate | RAM insufficiente | ||
ro.lmk.swap_free_low_percentage |
Il livello di swap senza costi come percentuale dello spazio di swap totale. `lmkd` utilizza questo valore come soglia per considerare il sistema come carente di spazio di swap. Se `lmkd` termina l'esecuzione quando c'è troppo spazio di swap, diminuisci la percentuale. Se gli arresti anomali di `lmkd` si verificano troppo tardi, consentendo gli arresti anomali OOM, aumenta la percentuale. | 20 |
10 |
ro.lmk.debug |
In questo modo vengono abilitati i log di debug di `lmkd`. Attiva il debug durante la sintonizzazione. | false |