Low Memory Killer Daemon

Der Android-Low-Memory-Killer-Daemon-Prozess ( lmkd ) überwacht den Speicherstatus eines laufenden Android-Systems und reagiert auf hohen Speicherdruck, indem er die am wenigsten wichtigen Prozesse beendet, um die Systemleistung auf einem akzeptablen Niveau zu halten.

Über Gedächtnisdruck

Bei einem Android-System, auf dem mehrere Prozesse parallel ausgeführt werden, kann es zu Situationen kommen, in denen der Systemspeicher erschöpft ist und Prozesse, die mehr Speicher benötigen, spürbare Verzögerungen erfahren. Speicherdruck , ein Zustand, in dem dem System der Speicher knapp wird, erfordert, dass Android Speicher freigibt (um den Druck zu verringern), indem unwichtige Prozesse gedrosselt oder beendet werden, Prozesse aufgefordert werden, nicht kritische zwischengespeicherte Ressourcen freizugeben usw.

In der Vergangenheit hat Android den Systemspeicherdruck mithilfe eines LMK-Treibers (Low Memory Killer) im Kernel überwacht, einem starren Mechanismus, der von fest codierten Werten abhängt. Ab Kernel 4.12 wird der LMK-Treiber aus dem Upstream-Kernel entfernt und der Userspace lmkd führt Speicherüberwachungs- und Prozessbeendigungsaufgaben durch.

Informationen zum Druckstillstand

Android 10 und höher unterstützen einen neuen lmkd Modus, der PSI-Monitore (Kernel Pressure Stall Information) zur Speicherdruckerkennung verwendet. Das PSI-Patchset im Upstream-Kernel (zurückportiert auf die Kernel 4.9 und 4.14) misst die Zeitspanne, um die Aufgaben aufgrund von Speichermangel verzögert werden. Da sich diese Verzögerungen direkt auf das Benutzererlebnis auswirken, stellen sie eine praktische Messgröße zur Bestimmung des Schweregrads der Speicherauslastung dar. Der Upstream-Kernel enthält auch PSI-Monitore, die es privilegierten Userspace-Prozessen (wie lmkd ) ermöglichen, Schwellenwerte für diese Verzögerungen festzulegen und Ereignisse vom Kernel zu abonnieren, wenn ein Schwellenwert überschritten wird.

PSI-Monitore im Vergleich zu Vm-Drucksignalen

Da die vmpressure Signale (die vom Kernel zur Speicherdruckerkennung generiert und von lmkd verwendet werden) häufig zahlreiche Fehlalarme enthalten, muss lmkd eine Filterung durchführen, um festzustellen, ob der Speicher tatsächlich unter Druck steht. Dies führt zu unnötigen lmkd Wakeups und der Nutzung zusätzlicher Rechenressourcen. Die Verwendung von PSI-Monitoren führt zu einer genaueren Speicherdruckerkennung und minimiert den Filteraufwand.

Verwendung von PSI-Monitoren

Um PSI-Monitore anstelle von vmpressure Ereignissen zu verwenden, konfigurieren Sie die Eigenschaft ro.lmk.use_psi . Der Standardwert ist true , sodass PSI-Monitore der Standardmechanismus zur Speicherdruckerkennung für lmkd sind. Da PSI-Monitore Kernel-Unterstützung erfordern, muss der Kernel die PSI-Backport-Patches enthalten und mit aktivierter PSI-Unterstützung kompiliert werden ( CONFIG_PSI=y ).

Nachteile des kernelinternen LMK-Treibers

Android veraltet den LMK-Treiber aufgrund einer Reihe von Problemen, darunter:

  • Geräte mit geringem RAM mussten aggressiv optimiert werden und selbst dann würden sie bei Workloads mit großem, dateigestütztem, aktivem Pagecache eine schlechte Leistung erbringen. Die schlechte Leistung führte zu Prügel und keinen Kills.
  • Der LMK-Kerneltreiber stützte sich auf Beschränkungen des freien Speichers, ohne Skalierung basierend auf der Speicherauslastung.
  • Aufgrund der Starrheit des Designs haben Partner den Treiber oft so angepasst, dass er auf ihren Geräten funktioniert.
  • Der LMK-Treiber war in die Slab-Shrinker-API eingebunden, die nicht für schwere Vorgänge wie die Suche nach Zielen und deren Tötung konzipiert war, was den vmscan Prozess verlangsamte.

Userspace lmkd

Der Userspace lmkd implementiert die gleiche Funktionalität wie der In-Kernel-Treiber, nutzt jedoch vorhandene Kernel-Mechanismen, um den Speicherdruck zu erkennen und abzuschätzen. Zu diesen Mechanismen gehören die Verwendung von Kernel-generierten vmpressure Ereignissen oder PSI-Monitoren (Pressure Stall Information), um Benachrichtigungen über den Speicherdruck zu erhalten, und die Verwendung von Speicher-Cgroup-Funktionen, um die jedem Prozess zugewiesenen Speicherressourcen basierend auf der Prozesswichtigkeit zu begrenzen.

Verwenden des Userspace lmkd in Android 10

In Android 9 und höher wird Userspace lmkd aktiviert, wenn kein kernelinterner LMK-Treiber erkannt wird. Da Userspace lmkd Kernel-Unterstützung für Speicher-Cgroups erfordert, muss der Kernel mit den folgenden Konfigurationseinstellungen kompiliert werden:

CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y

Tötungsstrategien

Userspace lmkd unterstützt Kill-Strategien basierend auf vmpressure Ereignissen oder PSI-Monitoren, deren Schweregrad und anderen Hinweisen wie der Swap-Nutzung. Die Tötungsstrategien unterscheiden sich zwischen Geräten mit wenig Speicher und Geräten mit hoher Leistung:

  • Auf Geräten mit wenig Speicher sollte das System im normalen Betriebsmodus einen höheren Speicherdruck tolerieren.
  • Auf Hochleistungsgeräten sollte die Speicherauslastung als ungewöhnliche Situation betrachtet und behoben werden, bevor sie sich auf die Gesamtleistung auswirkt.

Sie können die Kill-Strategie mithilfe der Eigenschaft ro.config.low_ram konfigurieren. Einzelheiten finden Sie unter Konfiguration mit geringem RAM .

Userspace lmkd unterstützt auch einen Legacy-Modus, in dem es Kill-Entscheidungen mit denselben Strategien wie der LMK-Treiber im Kernel trifft (d. h. Schwellenwerte für freien Speicher und Datei-Cache). Um den Legacy-Modus zu aktivieren, setzen Sie die Eigenschaft ro.lmk.use_minfree_levels auf true .

lmkd konfigurieren

Konfigurieren Sie lmkd für ein bestimmtes Gerät mithilfe der folgenden Eigenschaften.

Eigentum Verwenden Standard
ro.config.low_ram Geben Sie an, ob es sich bei dem Gerät um ein Gerät mit wenig RAM oder um ein Hochleistungsgerät handelt. false
ro.lmk.use_psi Verwenden Sie PSI-Monitore (anstelle von vmpressure Ereignissen). true
ro.lmk.use_minfree_levels Verwenden Sie Schwellenwerte für freien Speicher und Dateicache, um Entscheidungen zum Abbruch von Prozessen zu treffen (d. h. passen Sie sie an die Funktionalität des LMK-Treibers im Kernel an). false
ro.lmk.low Der minimale oom_adj Score für Prozesse, die bei einem niedrigen vmpressure Level beendet werden können. 1001
(deaktiviert)
ro.lmk.medium Der minimale oom_adj Score für Prozesse, die bei mittlerem vmpressure Level beendet werden können. 800
(zwischengespeicherte oder nicht wesentliche Dienste)
ro.lmk.critical Der minimale oom_adj Score für Prozesse, die bei einem kritischen vmpressure Level beendet werden können. 0
(jeder Prozess)
ro.lmk.critical_upgrade Aktivieren Sie das Upgrade auf die kritische Ebene. false
ro.lmk.upgrade_pressure Der maximale mem_pressure , bei dem die Ebene aktualisiert wird, weil das System zu viel austauscht. 100
(deaktiviert)
ro.lmk.downgrade_pressure Der minimale mem_pressure , bei dem ein vmpressure Ereignis ignoriert wird, da noch genügend freier Speicher verfügbar ist. 100
(deaktiviert)
ro.lmk.kill_heaviest_task Töten Sie die schwerste in Frage kommende Aufgabe (beste Entscheidung) im Vergleich zu jeder in Frage kommenden Aufgabe (schnelle Entscheidung). true
ro.lmk.kill_timeout_ms Dauer in Millisekunden nach einem Kill, wenn kein weiterer Kill durchgeführt wird. 0
(deaktiviert)
ro.lmk.debug Aktivieren Sie lmkd Debug-Protokolle. false

Beispielhafte Gerätekonfiguration:

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 verbessert den lmkd durch die Einführung einer neuen Tötungsstrategie. Die Killing-Strategie nutzt einen PSI-Mechanismus zur Speicherdruckerkennung, der in Android 10 eingeführt wurde. lmkd in Android 11 berücksichtigt die Speicherressourcennutzung und das Thrashing, um Speichermangel und Leistungseinbußen zu verhindern. Diese Tötungsstrategie ersetzt frühere Strategien und kann sowohl auf Geräten mit hoher Leistung als auch auf Geräten mit wenig RAM (Android Go) verwendet werden.

Kernel-Anforderungen

Für Android 11-Geräte erfordert lmkd die folgenden Kernelfunktionen:

  • Fügen Sie PSI-Patches hinzu und aktivieren Sie PSI (Backports verfügbar in den gängigen Android-Kerneln 4.9, 4.14 und 4.19).
  • Fügen Sie PIDFD-Unterstützungspatches hinzu (Backports, die in den gängigen Android-Kerneln 4.9, 4.14 und 4.19 verfügbar sind).
  • Schließen Sie für Geräte mit wenig RAM Speicher-Cgroups ein.

Der Kernel muss mit den folgenden Konfigurationseinstellungen kompiliert werden:

CONFIG_PSI=y

Konfigurieren von lmkd in Android 11

Die Speicherlöschstrategie in Android 11 unterstützt die unten aufgeführten Einstellknöpfe und Standardeinstellungen. Diese Funktionen funktionieren sowohl auf Hochleistungsgeräten als auch auf Geräten mit wenig RAM.

Eigentum Verwenden Standard
Hochleistung Wenig RAM
ro.lmk.psi_partial_stall_ms Der teilweise PSI-Stallschwellenwert in Millisekunden zum Auslösen einer Benachrichtigung über wenig Arbeitsspeicher. Wenn das Gerät Benachrichtigungen über Speicherauslastung zu spät erhält, verringern Sie diesen Wert, um frühere Benachrichtigungen auszulösen. Wenn unnötigerweise Benachrichtigungen über Speicherauslastung ausgelöst werden, erhöhen Sie diesen Wert, um das Gerät weniger empfindlich gegenüber Störungen zu machen. 70 200
ro.lmk.psi_complete_stall_ms Der vollständige PSI-Stallschwellenwert in Millisekunden zum Auslösen kritischer Speicherbenachrichtigungen. Wenn das Gerät Benachrichtigungen über kritische Speicherauslastung zu spät erhält, verringern Sie diesen Wert, um frühere Benachrichtigungen auszulösen. Wenn unnötigerweise Benachrichtigungen über kritische Speicherauslastung ausgelöst werden, erhöhen Sie diesen Wert, um das Gerät weniger empfindlich gegenüber Störungen zu machen. 700
ro.lmk.thrashing_limit Die maximale Anzahl von Arbeitssatz-Refaults wird als Prozentsatz der gesamten dateigestützten Seitencache-Größe angegeben. Arbeitssatz-Refaults über diesem Wert bedeuten, dass davon ausgegangen wird, dass das System seinen Seitencache überlastet. Wenn die Leistung des Geräts während der Speicherauslastung beeinträchtigt wird, verringern Sie den Wert, um Thrashing zu begrenzen. Wenn die Leistung des Geräts aus Thrashing-Gründen unnötig beeinträchtigt wird, erhöhen Sie den Wert, um mehr Thrashing zu ermöglichen. 100 30
ro.lmk.thrashing_limit_decay Der Thrashing-Schwellenwertabfall, ausgedrückt als Prozentsatz des ursprünglichen Schwellenwerts, wird verwendet, um den Schwellenwert zu senken, wenn sich das System nicht erholt, selbst nach einem Kill. Wenn kontinuierliches Prügeln zu unnötigen Kills führt, verringern Sie den Wert. Wenn die Reaktion auf kontinuierliches Thrashing nach einem Kill zu langsam ist, erhöhen Sie den Wert. 10 50
ro.lmk.swap_util_max Die maximale Menge an ausgelagertem Speicher als Prozentsatz des gesamten auswechselbaren Speichers. Wenn der ausgelagerte Speicher diesen Grenzwert überschreitet, bedeutet das, dass das System den größten Teil seines auswechselbaren Speichers ausgelagert hat und immer noch unter Druck steht. Dies kann passieren, wenn nicht austauschbare Zuweisungen Speicherdruck erzeugen, der nicht durch Auslagern entlastet werden kann, da der größte Teil des auswechselbaren Speichers bereits ausgelagert ist. Der Standardwert ist 100, wodurch diese Prüfung effektiv deaktiviert wird. Wenn die Leistung des Geräts während der Speicherauslastung beeinträchtigt wird, während die Swap-Nutzung hoch ist und der freie Swap-Level nicht auf ro.lmk.swap_free_low_percentage sinkt, verringern Sie den Wert, um die Swap-Nutzung zu begrenzen. 100 100

Die folgenden alten Stimmknöpfe funktionieren auch mit der neuen Tötungsstrategie.

Eigentum Verwenden Standard
Hochleistung Wenig RAM
ro.lmk.swap_free_low_percentage Der Anteil des freien Swaps als Prozentsatz des gesamten Swap-Speicherplatzes. „lmkd“ verwendet diesen Wert als Schwellenwert dafür, wann das System als Swap-Space-hungrig betrachtet werden soll. Wenn „lmkd“ abstürzt, während im Swap zu viel Platz vorhanden ist, verringern Sie den Prozentsatz. Wenn „lmkd“-Kills zu spät erfolgen und OOM-Kills möglich sind, erhöhen Sie den Prozentsatz. 20 10
ro.lmk.debug Dadurch werden „lmkd“-Debug-Protokolle aktiviert. Aktivieren Sie das Debuggen während der Optimierung. false