Android 17 und höher unterstützt den Memory Limiter, einen Systemdienst, der die Arbeitsspeichernutzung von Anwendungsprozessen mithilfe von Linux-Cgroup v2 überwacht und begrenzt. Der Arbeitsspeicherbegrenzer verhindert, dass einzelne Apps zu viel Systemspeicher verbrauchen. Dadurch wird der systemspezifische Arbeitsspeicherbedarf reduziert und das aggressive Beenden wichtiger Prozesse aufgrund von Arbeitsspeichermangel (Out-of-Memory, OOM) verhindert.
Mechanismus
Der Memory Limiter ist in den Activity Manager Service (AMS) integriert, um Ereignisse im Prozesslebenszyklus und Statusänderungen zu verfolgen. Der Memory Limiter erzwingt Arbeitsspeicherlimits mithilfe des Linux-Kernel-Dateisystems „cgroup v2“.
Damit der Memory Limiter verwendet werden kann, muss der Geräte-Kernel cgroup v2 und den memory-Controller unterstützen. Der Dienst basiert insbesondere auf den folgenden Attributen:
memory.high- Ein weiches Limit. Wird das Limit überschritten, wird der Prozess gedrosselt und der Kernel versucht, Arbeitsspeicher zurückzugewinnen.
memory.swap.max- Begrenzt die Menge an Auslagerungsspeicher, die der Prozess verwenden kann.
Auswirkungen auf Apps
Apps, die ihre Arbeitsspeicherlimits nicht überschreiten, sind vom Memory Limiter nicht betroffen.
Wenn eine App ihr memory.high-Limit überschreitet, entfernt der Kernel den dateibasierten Speicher der App und tauscht den anonymen Speicher aus, damit die App das Limit nicht überschreitet. Durch das Entfernen und Ersetzen kann es sein, dass die App langsamer ausgeführt wird.
Wenn die App weiterhin anonymen Arbeitsspeicher zuweist und auf dem Gerät kein Swap-Speicher mehr verfügbar ist, kann es im Extremfall passieren, dass die App keinen Arbeitsspeicher mehr zuweisen kann und abstürzt.
Prozessmonitoring
Der Arbeitsspeicherbegrenzer überwacht standardmäßig App-Prozesse (UID >= 10000). Systemprozesse sind in der Regel ausgenommen, um die Stabilität des Kernsystems zu überprüfen.
Der Memory Limiter weist Arbeitsspeicherlimits basierend auf dem Status des Prozesses zu:
Sichtbare Prozesse befinden sich in einem Zustand, in dem sie dem Nutzer eine Benutzeroberfläche anzeigen können. Wenn ein Prozess eine Benutzeroberfläche anzeigt, wird möglicherweise ein größerer RAM-Arbeitssatz erwartet. Daher wird ihm ein großzügigeres Arbeitsspeicherlimit gewährt.
Nicht sichtbare Prozesse sind in einem Zustand, in dem sie aktiv Aufgaben ausführen, aber keine Benutzeroberfläche darstellen. Sie benötigen dafür Speicher, aber weniger als für die Anzeige einer Benutzeroberfläche. Daher gilt für sie ein restriktiveres Limit.
In der folgenden Tabelle werden bestimmte Prozessstatus den Arbeitsspeicherlimits zugeordnet:
| Prozessstatus | Arbeitsspeicherlimit |
|---|---|
PERSISTENT | Uneingeschränkt |
PERSISTENT_UI | Uneingeschränkt |
TOP | Sichtbar |
BOUND_TOP | Sichtbar |
FOREGROUND_SERVICE | Nicht sichtbar |
BOUND_FOREGROUND_SERVICE | Nicht sichtbar |
IMPORTANT_FOREGROUND | Sichtbar |
IMPORTANT_BACKGROUND | Nicht sichtbar |
TRANSIENT_BACKGROUND | Nicht sichtbar |
BACKUP | Nicht sichtbar |
SERVICE | Nicht sichtbar |
RECEIVER | Nicht sichtbar |
TOP_SLEEPING | Sichtbar |
HEAVY_WEIGHT | Nicht sichtbar |
HOME | Nicht sichtbar |
LAST_ACTIVITY | Nicht sichtbar |
CACHED_ACTIVITY | Im Cache |
CACHED_ACTIVITY_CLIENT | Im Cache |
CACHED_RECENT | Im Cache |
CACHED_EMPTY | Im Cache |
Im Cache-Zustand werden Prozesse eingefroren und dann maximal zurückgefordert.
Wenn ein Prozess das zugewiesene memory.high-Limit überschreitet, erkennt der Memory Limiter das Ereignis und kann Debugging-Aktionen auslösen, z. B. ein Speicherprofil erfassen oder eine Anomalie in statsd protokollieren.
Konfiguration
Konfigurieren Sie den Memory Limiter mit einer XML-Datei auf der Partition vendor. Mit der Konfiguration können Sie absolute Speicherlimits an die spezifischen Speicherbeschränkungen des Geräts anpassen.
Dateipfad:
/vendor/etc/memory-limiter-config.xmlStandardkonfiguration:Wenn die Konfigurationsdatei nicht gefunden wird oder nicht lesbar oder ungültig ist, wird der Memory Limiter deaktiviert.
XML-Format
Die Konfigurationsdatei entspricht dem in memory-limiter-config.xsd definierten Schema. In der Datei können Sie mehrere Grenzwertsätze definieren. Der Dienst wählt den besten Satz basierend auf dem verfügbaren RAM des Geräts aus. Alle Speicherwerte werden in Mebibyte (MiB) angegeben.
<MemoryLimiterConfig>
<version>1</version>
<configList>
<limitSet>
<!-- Limits for a phone with at least 14G of ram: 8G/4G/4G/4G -->
<minimumRequiredMemTotal>14336</minimumRequiredMemTotal>
<memVisible>8192</memVisible>
<memNotVisible>4096</memNotVisible>
<swapVisible>4096</swapVisible>
<swapNotVisible>4096</swapNotVisible>
</limitSet>
</configList>
</MemoryLimiterConfig>
version- Eine positive Ganzzahl, die die Konfigurationsversion angibt. Muss 1 sein.
minimumRequiredMemTotal- Der mindestens erforderliche verfügbare Systemspeicher, damit dieses Limit gültig ist.
memVisible- Das für sichtbare Prozesse zulässige Speicherlimit (
memory.high). memNotVisible- Das für nicht sichtbare Prozesse zulässige Arbeitsspeicherlimit (
memory.high). swapVisible- Das für sichtbare Prozesse zulässige Swap-Limit (
memory.swap.max). swapNotVisible- Das Swap-Limit (
memory.swap.max) wurde für nicht sichtbare Prozesse überschritten.
Richtlinien für das Speicherlimit von Geräten
Beachten Sie beim Konfigurieren von Arbeitsspeicherlimits für Ihr Gerät die folgenden Richtlinien:
Grenzwerte an Hardwarefunktionen anpassen:Geräte-OEMs können Grenzwerte festlegen, die auf die Hardwarefunktionen ihrer Geräte zugeschnitten sind. Android empfiehlt die folgenden Bereiche:
- Sichtbare Prozesse:Mindestens die Hälfte und höchstens zwei Drittel des gesamten physischen RAM.
- Nicht sichtbare Prozesse:1/4 bis 1/3 des gesamten physischen RAM. OEMs können je nach Gerätefunktionen und Anwendungsfällen unterschiedliche Entscheidungen treffen.
Keine Laufzeit-API für Apps:Ab Android 17 (SDK 37) haben Apps keine API mehr, um die Speicherlimits zur Laufzeit abzufragen. OEMs sollten dies berücksichtigen und vermeiden, Limits zu niedrig festzulegen, damit Apps bei angemessenen Anwendungsfällen nicht an die Limits stoßen.
Universelle Konfiguration:Die Limits gelten für alle App-Prozesse auf dem Gerät, einschließlich vorinstallierter Apps. Es gibt keine Zulassungsliste, um bestimmte Apps von diesen Einschränkungen auszunehmen.
Konfiguration ändern
So ändern Sie systemweite Limits:
/vendor/etc/memory-limiter-config.xmländern- Starte das Gerät neu oder starte
system_serverneu, damit die Änderungen wirksam werden.
Shell-Befehle
Mit dem Befehl am memory-limiter können Sie und Entwickler zur Laufzeit mit dem Dienst interagieren, um ihn zu entwickeln und zu testen:
am memory-limiter <SUB-COMMAND>Status
Der Unterbefehl status gibt den Betriebsstatus des Memory Limiters zurück:
adb shell am memory-limiter statusBeispielausgabe:
Memory limiter
enabled monitoring=true ignored=none
visibleMem=1948MB visibleSwap=974MB
notVisibleMem=974MB notVisibleSwap=487MB
started=36 watched=36 watch-failed=0
events=0 processes=36 process-hwm=36
Wichtige Felder in der Ausgabe:
monitoring- Gibt an, ob der Limiter Prozesse aktiv überwacht.
visibleMemundnotVisibleMem- Geben Sie die berechneten absoluten Speicherlimits für jeden Bundesstaat an.
events- Die Häufigkeit, mit der ein Prozess sein Limit überschritten hat.
processes- Die Anzahl der überwachten Prozesse.
ignorieren
Mit dem Unterbefehl ignore wird eine UID oder alle Prozesse vorübergehend von der Einschränkung ausgeschlossen. Diese Aktion ist nützlich für Leistungstests oder wenn eine bestimmte App ihre Limits überschreiten darf.
adb shell am memory-limiter ignore 10087 // Ignore a specific UIDadb shell am memory-limiter ignore all // Ignore all processes (effectively disables limiting)adb shell am memory-limiter ignore none // Resume normal operation
Manuell
Mit dem Unterbefehl manual werden die berechneten Grenzwerte für einen bestimmten Prozess (nach Prozess-ID oder PID) mit einem benutzerdefinierten absoluten Wert in Megabyte (MB) überschrieben:
adb shell am memory-limiter manual 1234 1024 // Set a 1024 MB limit for PID 1234adb shell am memory-limiter manual 1234 none // Remove the manual override for PID 1234
Manuelle Überschreibungen gelten nur für den Lebenszyklus des Prozesses. Wenn der Prozess neu gestartet wird, werden die Standardlimits basierend auf dem Status wiederhergestellt.