Demone killer di memoria insufficiente

Il processo Android low memory killer daemon ( lmkd ) monitora lo stato della memoria di un sistema Android in esecuzione e reagisce a un'elevata pressione di memoria uccidendo i processi meno essenziali per mantenere il sistema a livelli accettabili.

Sulla pressione della memoria

Un sistema Android che esegue più processi in parallelo può riscontrare situazioni in cui la memoria di sistema è esaurita e i processi che richiedono più memoria subiscono notevoli ritardi. La pressione della memoria , uno stato in cui il sistema sta esaurendo la memoria, richiede ad Android di liberare memoria (per alleviare la pressione) limitando o eliminando processi non importanti, richiedendo ai processi di liberare risorse memorizzate nella cache non critiche e così via.

Storicamente, Android ha monitorato 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 eliminazione dei processi.

Informazioni sullo stallo della pressione

Android 10 e versioni successive supportano una nuova modalità lmkd che usa i monitor PSI (kernel pressure stall information) per il rilevamento della pressione della memoria. Il set di patch PSI nel kernel upstream (backported ai kernel 4.9 e 4.14) misura la quantità di tempo in cui le attività vengono ritardate a causa della carenza di memoria. Poiché questi ritardi influiscono direttamente sull'esperienza dell'utente, rappresentano una metrica utile per determinare la gravità della pressione della memoria. Il kernel upstream include anche monitor PSI che consentono ai processi dello spazio utente privilegiato (come lmkd ) di specificare soglie per questi ritardi e di sottoscrivere eventi dal kernel quando una soglia viene superata.

Monitor PSI rispetto ai segnali di pressione virtuale

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 è sotto pressione reale. Ciò si traduce in lmkd non necessarie e nell'uso di risorse di calcolo aggiuntive. L'utilizzo dei monitor PSI consente un rilevamento più accurato della pressione della memoria e riduce al minimo l'overhead di filtraggio.

Utilizzo dei monitor PSI

Per utilizzare i monitor PSI invece degli eventi vmpressure , configurare la proprietà ro.lmk.use_psi . L'impostazione predefinita è true , rendendo PSI monitor il meccanismo predefinito di rilevamento della pressione della memoria per lmkd . Poiché i monitor PSI richiedono il supporto del kernel, il kernel deve includere le patch del backport PSI ed essere compilato con il supporto PSI abilitato ( CONFIG_PSI=y ).

Svantaggi del driver LMK nel kernel

Android depreca il driver LMK a causa di una serie di problemi, tra cui:

  • I dispositivi a bassa RAM dovevano essere ottimizzati in modo aggressivo e anche in quel caso avrebbero funzionato male sui carichi di lavoro con una grande cache di pagina attiva supportata da file. Le scarse prestazioni hanno provocato thrashing e nessuna uccisione.
  • Il driver del kernel LMK si basava sui limiti di memoria libera, senza ridimensionamento basato sulla 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 di riduzione lastre, che non è stata progettata per operazioni pesanti come la ricerca di obiettivi e l'uccisione, il che ha rallentato il processo vmscan .

Spazio utente lmkd

lmkd implementa la stessa funzionalità del driver interno al kernel ma utilizza i meccanismi del kernel esistenti per rilevare e stimare la pressione della memoria. Tali meccanismi includono l'utilizzo di eventi vmpressure generati dal kernel o monitor PSI (Pression Stall Information) per ricevere notifiche sui livelli di pressione della memoria e l'utilizzo delle funzionalità di cgroup di memoria per limitare le risorse di memoria allocate a ciascun processo in base all'importanza del processo.

Utilizzo dello spazio utente lmkd in Android 10

In Android 9 e versioni successive, lo spazio utente lmkd attiva se non viene rilevato un driver LMK nel 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

Strategie di uccisione

Userspace lmkd supporta strategie kill basate su eventi vmpressure o monitor PSI, la loro gravità e altri suggerimenti come l'utilizzo dello swap. Le strategie di uccisione differiscono tra dispositivi con memoria insufficiente e dispositivi ad alte prestazioni:

  • Sui dispositivi con memoria insufficiente, il sistema dovrebbe tollerare una maggiore pressione della memoria come normale modalità di funzionamento.
  • Sui dispositivi ad alte prestazioni, la pressione della memoria dovrebbe essere vista come una situazione anormale e risolta prima che influisca sulle prestazioni complessive.

È possibile configurare la strategia kill utilizzando la proprietà ro.config.low_ram . Per i dettagli, vedere Configurazione ram bassa .

Userspace lmkd supporta anche una modalità legacy in cui prende decisioni di kill utilizzando le stesse strategie del driver LMK nel kernel (ovvero, memoria libera e soglie della cache dei file). Per abilitare la modalità legacy, imposta la proprietà ro.lmk.use_minfree_levels su true .

Configurazione di lmkd

Configura lmkd per un dispositivo specifico usando le seguenti proprietà.

Proprietà Uso Predefinito
ro.config.low_ram Specificare se il dispositivo è un dispositivo a bassa RAM o ad alte prestazioni. false
ro.lmk.use_psi Utilizzare i monitor PSI (invece degli eventi vmpressure ). true
ro.lmk.use_minfree_levels Utilizzare la memoria libera e le soglie della cache dei file per prendere decisioni di eliminazione dei processi (ovvero, far corrispondere la funzionalità del driver LMK nel kernel). false
ro.lmk.low Il punteggio minimo di oom_adj per i processi idonei a essere uccisi a un livello di pressione vmpressure basso. 1001
(Disabilitato)
ro.lmk.medium Il punteggio minimo di oom_adj per i processi idonei a essere uccisi a livello di vmpressure medio. 800
(servizi memorizzati nella cache o non essenziali)
ro.lmk.critical Il punteggio minimo di oom_adj per i processi idonei a essere eliminati a un livello critico di vmpressure . 0
(qualsiasi processo)
ro.lmk.critical_upgrade Abilita l'aggiornamento al livello critico. false
ro.lmk.upgrade_pressure Il massimo mem_pressure a cui il livello viene aggiornato perché il sistema sta scambiando troppo. 100
(Disabilitato)
ro.lmk.downgrade_pressure Il valore minimo di mem_pressure a cui un evento vmpressure viene ignorato perché è ancora disponibile memoria sufficiente. 100
(Disabilitato)
ro.lmk.kill_heaviest_task Elimina l'attività idonea più pesante (decisione migliore) rispetto a qualsiasi attività idonea (decisione rapida). true
ro.lmk.kill_timeout_ms Durata in millisecondi dopo un'uccisione quando non verranno eseguite ulteriori uccisioni. 0
(Disabilitato)
ro.lmk.debug Abilita i log di debug lmkd . false

Esempio di configurazione del dispositivo:

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

Userspace lmkd in Android 11

Android 11 migliora l' lmkd introducendo una nuova strategia di uccisione. La strategia di uccisione 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 prevenire la carenza di memoria e il degrado delle prestazioni. Questa strategia di uccisione sostituisce le strategie precedenti e può essere utilizzata su dispositivi sia ad alte prestazioni che a bassa RAM (Android Go).

Requisiti del kernel

Per i dispositivi Android 11, lmkd richiede le seguenti funzionalità del kernel:

  • Includi patch PSI e abilita PSI (backport disponibili nei kernel comuni Android 4.9, 4.14 e 4.19).
  • Include patch di supporto PIDFD (backport disponibili nei kernel comuni 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

Configurazione di lmkd in Android 11

La strategia di uccisione della memoria in Android 11 supporta le manopole di sintonizzazione e le impostazioni predefinite elencate di seguito. Queste funzionalità funzionano sia su dispositivi ad alte prestazioni che a bassa RAM.

Proprietà Uso Predefinito
Alte prestazioni 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 le notifiche di esaurimento della memoria troppo tardi, diminuire questo valore per attivare le notifiche precedenti. Se le notifiche di pressione della memoria si attivano inutilmente, aumentare 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 critica. Se il dispositivo riceve notifiche di pressione di memoria critica troppo tardi, diminuire questo valore per attivare notifiche precedenti. Se le notifiche di pressione della memoria critica si attivano inutilmente, aumentare questo valore per rendere il dispositivo meno sensibile al rumore. 700
ro.lmk.thrashing_limit La quantità massima di set di lavoro è predefinita come percentuale della dimensione totale della cache di pagina supportata da file. I valori di default del workingset al di sopra di questo valore indicano che il sistema sta consumando la sua pagecache. Se le prestazioni del dispositivo sono influenzate durante la pressione della memoria, diminuire il valore per limitare il thrashing. Se le prestazioni del dispositivo vengono interrotte inutilmente per motivi di thrashing, aumentare il valore per consentire più thrashing. 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 si ripristina, anche dopo un'uccisione. Se il battito continuo produce uccisioni non necessarie, diminuire il valore. Se la risposta al battito continuo dopo un'uccisione è troppo lenta, aumentare il valore. 10 50
ro.lmk.swap_util_max La quantità massima di memoria scambiata come percentuale della memoria scambiabile totale. Quando la memoria scambiata supera questo limite, significa che il sistema ha scambiato la maggior parte della sua memoria scambiabile ed è ancora sotto pressione. Ciò può accadere quando le allocazioni non sostituibili generano una pressione di memoria che non può essere alleviata dallo scambio perché la maggior parte della memoria sostituibile è già stata sostituita. Il valore predefinito è 100, che disabilita effettivamente questo controllo. Se le prestazioni del dispositivo sono influenzate durante la pressione della memoria mentre l'utilizzo dello scambio è elevato e il livello di scambio gratuito non scende a ro.lmk.swap_free_low_percentage , diminuire il valore per limitare l'utilizzo dello scambio. 100 100

Le seguenti vecchie manopole di sintonia funzionano anche con la nuova strategia di uccisione.

Proprietà Uso Predefinito
Alte prestazioni RAM insufficiente
ro.lmk.swap_free_low_percentage Il livello di scambio gratuito come percentuale dello spazio di scambio totale. `lmkd` usa questo valore come soglia per quando considerare il sistema come uno spazio di scambio affamato. Se `lmkd` uccide mentre c'è troppo spazio nello scambio, diminuisci la percentuale. Se le uccisioni di `lmkd` avvengono troppo tardi, consentendo che le uccisioni OOM avvengano, aumenta la percentuale. 20 10
ro.lmk.debug Questo abilita i log di debug `lmkd`. Abilita il debug durante l'ottimizzazione. false