Demone killer con poca memoria

Il processo Android Low Memory Killer Daemon ( lmkd ) monitora lo stato della memoria di un sistema Android in esecuzione e reagisce all'elevata pressione della memoria uccidendo i processi meno essenziali per mantenere le prestazioni del 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 che Android liberi memoria (per alleviare la pressione) limitando o uccidendo processi non importanti, richiedendo processi per liberare risorse memorizzate nella cache non critiche e così via.

Storicamente, Android monitorava la pressione della memoria del sistema utilizzando un driver LMK (Low Memory Killer) interno al kernel, un meccanismo rigido che dipende da valori codificati. A partire dal kernel 4.12, il driver LMK viene rimosso dal kernel upstream e lo spazio utente lmkd esegue attività di monitoraggio della memoria e di uccisione dei processi.

Informazioni sullo stallo della pressione

Android 10 e versioni successive supportano una nuova modalità lmkd che utilizza il monitoraggio delle informazioni di stallo della pressione del kernel (PSI) per il rilevamento della pressione della memoria. Il set di patch PSI nel kernel upstream (backport sui 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à del carico di memoria. Il kernel upstream include anche monitor PSI che consentono ai processi privilegiati dello spazio utente (come lmkd ) di specificare soglie per questi ritardi e di sottoscrivere eventi dal kernel quando una soglia viene superata.

Monitor PSI rispetto ai segnali vmpressione

Poiché i segnali vmpressure (generati dal kernel per il rilevamento del sovraccarico della memoria e utilizzati da lmkd ) spesso includono numerosi falsi positivi, lmkd deve eseguire un filtraggio per determinare se la memoria è sotto reale pressione. Ciò si traduce in risvegli lmkd non necessari e nell'uso di risorse computazionali aggiuntive. L'utilizzo dei monitor PSI garantisce un rilevamento più accurato del carico di memoria e riduce al minimo l'overhead di filtraggio.

Utilizzo di monitor PSI

Per utilizzare i monitoraggi PSI invece degli eventi vmpressure , configurare la proprietà ro.lmk.use_psi . Il valore predefinito è true , rendendo i monitor PSI il meccanismo predefinito di rilevamento del sovraccarico 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 interno al kernel

Android depreca 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 avrebbero funzionato male con carichi di lavoro con pagecache attiva supportata da file di grandi dimensioni. Le scarse prestazioni hanno provocato percosse e nessuna uccisione.
  • Il driver del kernel LMK si basava su 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 collegava all'API del restringente lastra, che non era progettata per operazioni pesanti come la ricerca di obiettivi e la loro uccisione, il che rallentava il processo vmscan .

Spazio utente lmkd

Lo spazio utente lmkd implementa la stessa funzionalità del driver interno al kernel ma utilizza i meccanismi del kernel esistenti per rilevare e stimare il carico di memoria. Tali meccanismi includono l'utilizzo di eventi vmpressure generati dal kernel o monitoraggi PSI (Pressure Stall Information) per ricevere notifiche sui livelli di pressione della memoria e l'utilizzo delle funzionalità 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, userspace lmkd si 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

Spazio utente lmkd supporta strategie di kill basate su eventi vmpressure o monitoraggi PSI, sulla loro gravità e altri suggerimenti come l'utilizzo dello swap. Le strategie di kill differiscono tra dispositivi con memoria ridotta e dispositivi ad alte prestazioni:

  • Sui dispositivi con memoria insufficiente, il sistema dovrebbe tollerare un utilizzo della memoria più elevato come modalità operativa normale.
  • Sui dispositivi ad alte prestazioni, il sovraccarico della memoria dovrebbe essere visto come una situazione anomala e risolto prima che influisca sulle prestazioni generali.

Puoi configurare la strategia di kill utilizzando la proprietà ro.config.low_ram . Per i dettagli, vedere Configurazione con ram basso .

Userspace lmkd supporta anche una modalità legacy in cui prende decisioni di kill utilizzando le stesse strategie del driver LMK in-kernel (ovvero, soglie di memoria libera e cache di 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 utilizzando le seguenti proprietà.

Proprietà Utilizzo Predefinito
ro.config.low_ram Specificare se il dispositivo è un dispositivo con poca 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 sull'interruzione del processo (ovvero, corrispondere alla funzionalità del driver LMK in-kernel). false
ro.lmk.low Il punteggio oom_adj minimo per i processi idonei a essere terminati a un livello vmpressure basso. 1001
(Disabilitato)
ro.lmk.medium Il punteggio oom_adj minimo per i processi idonei a essere terminati a un livello vmpressure medio. 800
(servizi memorizzati nella cache o non essenziali)
ro.lmk.critical Il punteggio oom_adj minimo per i processi idonei a essere terminati al livello critico vmpressure . 0
(qualsiasi processo)
ro.lmk.critical_upgrade Abilita l'aggiornamento al livello critico. false
ro.lmk.upgrade_pressure La mem_pressure massima alla quale il livello viene aggiornato perché il sistema sta effettuando troppi scambi. 100
(Disabilitato)
ro.lmk.downgrade_pressure Il valore minimo mem_pressure al quale un evento vmpressure viene ignorato perché è ancora disponibile memoria libera 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 verrà eseguita alcuna uccisione aggiuntiva. 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

Spazio utente lmkd in Android 11

Android 11 migliora l' lmkd introducendo una nuova strategia di uccisione. La strategia di kill utilizza un meccanismo PSI per il rilevamento del sovraccarico 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 l'esaurimento della memoria e il degrado delle prestazioni. Questa strategia di uccisione sostituisce le strategie precedenti e può essere utilizzata sia su dispositivi ad alte prestazioni che con poca 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, includere 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 eliminazione della memoria in Android 11 supporta le manopole di regolazione e le impostazioni predefinite elencate di seguito. Queste funzionalità funzionano sia su dispositivi ad alte prestazioni che con poca RAM.

Proprietà Utilizzo Predefinito
Alte prestazioni RAM bassa
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 utilizzo della memoria troppo tardi, diminuire questo valore per attivare le notifiche prima. Se le notifiche relative al sovraccarico 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 utilizzo critico della memoria troppo tardi, diminuire questo valore per attivare le notifiche prima. Se le notifiche di utilizzo critico della memoria si attivano inutilmente, aumentare questo valore per rendere il dispositivo meno sensibile al rumore. 700
ro.lmk.thrashing_limit La quantità massima di default del workingset come percentuale della dimensione totale della pagecache supportata da file. I valori predefiniti del workingset superiori a questo valore indicano che si ritiene che il sistema stia distruggendo la cache della pagina. Se le prestazioni del dispositivo vengono influenzate durante l'utilizzo eccessivo della memoria, diminuire il valore per limitare il thrashing. Se le prestazioni del dispositivo vengono ridotte inutilmente per motivi di thrashing, aumentare il valore per consentire un maggiore 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 lo schiacciamento continuo produce uccisioni non necessarie, diminuisci il valore. Se la risposta alle percosse continue dopo un'uccisione è 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 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 scambiabili generano una pressione di memoria che non può essere alleviata dallo scambio perché la maggior parte della memoria scambiabile è già stata scambiata. Il valore predefinito è 100, che disabilita di fatto questo controllo. Se le prestazioni del dispositivo vengono influenzate durante il sovraccarico della memoria mentre l'utilizzo dello scambio è elevato e il livello dello scambio libero 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 regolazione funzionano anche con la nuova strategia di uccisione.

Proprietà Utilizzo Predefinito
Alte prestazioni RAM bassa
ro.lmk.swap_free_low_percentage Il livello di swap gratuito come percentuale dello spazio di swap totale. `lmkd` utilizza questo valore come soglia per quando considerare il sistema come affamato di spazio di swap. Se `lmkd` termina mentre c'è troppo spazio nello swap, diminuisci la percentuale. Se le uccisioni "lmkd" avvengono troppo tardi, consentendo l'esecuzione delle uccisioni OOM, aumenta la percentuale. 20 10
ro.lmk.debug Ciò abilita i log di debug di `lmkd`. Abilita il debug durante l'ottimizzazione. false