Android 17 und höher unterstützt den Memory-Management-Daemon (mmd), einen System-Daemon, der sich um die Daemon-Konfiguration, die abstimmbaren Parameter und die laufenden Swap- oder ZRAM-Wartungsaufgaben kümmert.
Hintergrund
Vor der Einführung von mmd waren die ZRAM-Konfigurationen von Android fragmentiert und boten nur begrenzte Anpassungsmöglichkeiten. mmd behebt dieses Problem, indem die ZRAM-Verwaltung zentralisiert wird. So können komplexere Konfigurationslogiken verwendet und neue Funktionen und Architekturverbesserungen einfacher hinzugefügt werden.
mmd sorgt auch für eine klare Trennung der Zuständigkeiten zwischen dem Java-basierten system_server-Prozess und dem Swap oder der Speicherverwaltung auf Kernelebene.
Architektur und ZRAM-Verwaltung
Nach Abschluss des Bootvorgangs (d. h. wenn sys.boot_completed=1) versucht mmd_setup, ZRAM mit den angegebenen Parametern zu konfigurieren. Nachdem die ZRAM-Einrichtung abgeschlossen ist, aktiviert das System den mmd-Dienst, der laufende Wartungsaufgaben übernimmt.
Im mmd-Projekt werden Wartungsvorgänge von system_server aus initiiert, indem Binder-Anfragen über die IMmd-Schnittstelle an mmd gesendet werden.
mmd übernimmt die Wartungsaufgaben für das ZRAM-Writeback, die Re-Kompression und das prozessbezogene Writeback basierend auf der eigenen internen Richtlinien-Engine. Sowohl die Planung über ActivityManagerService als auch die ZRAM-Wartungsrichtlinien können über Systemeigenschaften konfiguriert werden.
System server integration (system_server)
Der Java-basierte system_server-Prozess bestimmt, wann mmd aufgerufen wird. Bei diesem Verfahren werden globale Wartungsdurchläufe von gezielten Speicheroptimierungen pro App getrennt.
Normale Wartung der Nachbearbeitung
Die globale ZRAM-Wartung wird vom ActivityManagerService mit com.android.server.memory.ZramMaintenance gesteuert.

Abbildung 1. Ablauf für die ZRAM-Wartungsplanung.
- Planungsmodul:
ZramMaintenanceregistriert einen regelmäßigen Hintergrundjob mitJobSchedulervon Android. - Job-Einschränkungen:Um Ruckeln der Benutzeroberfläche im Vordergrund oder CPU-Konflikte zu vermeiden, wird der Job explizit mit
setRequiresDeviceIdle(true)undsetRequiresBatteryNotLow(true)konfiguriert. - Binder-Auslösung:Wenn der Scheduler
onStartJob()auslöst, ruftsystem_servermmd.doZramMaintenanceAsync()auf. Dies ist ein unidirektionaler asynchroner Binder-Aufruf.system_serverblockiert nicht und wartet nicht, bis die Wartungsdurchläufe abgeschlossen sind.mmdstellt dies in die Warteschlange eines Hintergrund-Worker-Threads, um die Neukomprimierung und das Zurückschreiben sequenziell auszuführen.
Rückschreiben pro Prozess
Das gezielte Entfernen von Arbeitsspeicher pro Prozess wird vom ActivityManagerService über com.android.server.am.CachedAppOptimizer verwaltet.

Abbildung 2: MMD-Writeback-Ablauf pro Prozess.
Wenn ein Prozess in den Hintergrund-Cache-Status wechselt, führt ActivityManager eine Speicherverdichtung durch. Wenn ein Low-Memory-Kill des Prozesses für den Nutzer sichtbar wäre, d. h. der Prozess hostet eine Aktivität, und wenn der prozessbezogene ZRAM-Writeback den Speicherbedarf des Prozesses auf nahezu null reduzieren würde, führt das System die folgenden Schritte aus:
- Nach der Komprimierung sendet
CachedAppOptimizereine verzögerte Nachricht (ZRAM_WRITEBACK_MSG) an den internen Komprimierungs-Handler (verzögert ummZramWritebackWaitSeconds). - Wenn die Verzögerung abgelaufen ist, öffnet ActivityManager einen sicheren Prozessdateideskriptor
pidfd. - Der Systemserver ruft
mmd.asyncWritebackProcessZramMemory(pfd, callback)auf. mmdführt den prozessbezogenen Writeback-ioctl aus und meldet das Ergebnis überIMmdProcessWritebackCallback. Bei Erfolg kennzeichnet ActivityManager den Prozessdatensatz (setIsZramWrittenBack(app, true)), um dieoom_score_adjdes Prozesses zu steigern, und protokolliert Messwerte inFrameworkStatsLog.ZRAM_WRITEBACK_EVENT.
Prefetch pro Prozess
Wenn ein Nutzer eine zuvor im Cache gespeicherte App neu startet (die aufgrund von UNFREEZE_REASON_ACTIVITY reaktiviert wurde), minimiert ActivityManager die App-Startlatenz, die durch schwerwiegende Seitenfehler aus dem Sicherungsspeicher verursacht wird:
CachedAppOptimizerfängt das Ereignis zum Aufheben des Einfrierens ab und ruftprefetchZram(app)auf.- Der Systemserver sendet die
pidfdder App über Binder mitmmd.asyncPrefetchProcessZramMemory(pfd).mmdgibt den ioctlZRAM_ANDROID_IOC_PROCESS_PREFETCHaus und weist den Kernel an, ausgelagerte Seiten asynchron wieder in den RAM vorab abzurufen, während der Haupt-UI-Thread der App initialisiert wird.
Übersicht über Wartungs- und Nachbearbeitungsaufgaben
In diesem Abschnitt werden die Hintergrundwartungsvorgänge und Nachbearbeitungsaufgaben beschrieben, die von mmd ausgeführt werden, um den Swap-Speicher und den Systemspeicher zu optimieren.
Wartung in mmd
In mmd bezieht sich Wartung auf geplante Hintergrundwartungsdurchläufe, die die Nutzung von Swap-Space und physischem Arbeitsspeicher optimieren, ohne die Leistung aktiver Nutzer im Vordergrund zu beeinträchtigen. Anstatt kontinuierliche, synchrone Sweeps durchzuführen, die zu starken CPU-Aktivierungen und UI-Rucklern führen würden, wird die Wartung asynchron ausgeführt:
system_serverlöst regelmäßigdoZramMaintenanceAsync()in Binder aus.mmdstellt die Anfrage in eine Warteschlange für HintergrundaufgabenLowPrioWorkItem::ZramMaintenance.In
mmdgibt es einen einzelnen Worker-Thread, der sowohl eine Warteschlange mit hoher Priorität als auch eine Warteschlange mit niedriger Priorität verwaltet. Arbeitselemente mit hoher Priorität (z. B. das Vorabrufen pro Prozess) werden zuerst verarbeitet und können Arbeitselemente mit niedriger Priorität unterbrechen. Wartung und prozessbezogenes Zurückschreiben werden als Arbeitselemente mit niedriger Priorität ausgeführt. Wenn der Arbeitsthread gestartet wird, führt er zwei primäre Wartungsvorgänge sequenziell aus:ZRAM-Neukomprimierung:Durchsucht vorhandene Swap-Seiten und komprimiert inaktive Seiten mit einem sekundären Komprimierungsalgorithmus mit höherem Verhältnis, z. B.
zstd.ZRAM-Writeback:Scannt inaktive Seiten und entfernt sie vollständig aus dem RAM in den Sicherungs-Flash-Speicher eines Loop-Geräts aus einer Datei auf
/data.
Nachbearbeitungsaufgaben in ZRAM
Im Linux-Kernel-ZRAM-Modul und in der mmd-Architektur sind Nachbearbeitungsaufgaben die asynchronen Transformationen, die auf Speicherseiten angewendet werden, nachdem sie bereits über die standardmäßigen Reclaim-Pfade des Kernels (kswapd oder Verdichtung) ausgelagert wurden.
Wenn eine Seite zum ersten Mal ausgelagert wird, priorisiert das System die Geschwindigkeit: Es verwendet einen schnellen primären Komprimierungsalgorithmus (wie lz4) und speichert die komprimierte Seite im RAM. Im Laufe der Zeit werden jedoch viele ausgelagerte Seiten inaktiv, z. B. im Hintergrund zwischengespeicherte Apps, die stundenlang nicht fortgesetzt werden. Das Speichern von inaktiven Seiten in schnellem, leicht komprimiertem ZRAM ist ineffizient.
Pipeline für die Nachbearbeitung
mmd implementiert einen mehrstufigen Nachbearbeitungszyklus, um diese Seiten zu optimieren:

Abbildung 3: mmd-Seitenlebenszyklus.
Phase 1: Erster Swap-Out (schnelle Komprimierung): Der Arbeitsspeicher wird zuerst durch kswapd oder die App-Kompaktierung freigegeben. In der Regel wird diese erste Rückforderung mit einem schnellen Komprimierungsalgorithmus wie
lz4durchgeführt und der Inhalt wird im RAM gespeichert.Phase 2: Markierung im Leerlauf (Alterung und Tracking):
mmd-Leerlauf-Tracking greift auf den Kernel-Speicher-Tracker (CONFIG_ZRAM_TRACK_ENTRY_ACTIME) zu oder verwendet seinen Software-Leerlauf-Marker, um zu verfolgen, wie lange Seiten nicht verwendet wurden.Phase 3: Nachbearbeitung 1 – Re-Kompression (Speicheroptimierung im Arbeitsspeicher): Seiten, die das Leerlaufalter für die Re-Kompression (
min_idle_secondsbismax_idle_seconds) erreichen, werden neu komprimiert.mmdschreibt in/sys/block/zram0/recompress, um den Kernel anzuweisen, die Seitelz4zu dekomprimieren und mitzstdneu zu komprimieren. Dadurch wird physischer RAM zurückgewonnen, ohne dass der Flash-Speicher abgenutzt wird.Phase 4: Nachbearbeitung 2 – Zurückschreiben (Entfernen in den Flash-Speicher): Wenn der Speicherdruck anhält und Seiten das Alter für das Zurückschreiben im Leerlauf erreichen (in der Regel 20 Stunden oder mehr), löst
mmddas Zurückschreiben aus.mmdschreibt in/sys/block/zram0/idleund/sys/block/zram0/writeback, um die komprimierte Seite vollständig aus dem RAM in den Sicherungs-Flash-Speicher zu verschieben.
ZRAM-Einrichtung konfigurieren
mmd lädt und verarbeitet die folgenden ZRAM-Einrichtungseigenschaften:
| Attribut | Verwenden | Standard |
|---|---|---|
mmd.zram.enabled |
Gibt an, ob die mmd-ZRAM-Einrichtung aktiviert ist. |
false |
mmd.zram.num_devices |
Die Anzahl der zu konfigurierenden ZRAM-Geräte. Für die Nummer N müssen die Geräte zram0 bis zram<N-1> vorhanden sein, bevor das System sys.boot_completed=1 festlegt.
Eigenschaften in der Liste der ZRAM-Geräte können gerätespezifisch konfiguriert werden.
|
1 |
mmd.zram.device_priority |
Prioritätswerte, die beim Aufrufen von swapon übergeben werden sollen. |
Nicht festgelegt |
mmd.zram.comp_algorithm |
ZRAM-Komprimierungsalgorithmus. Wenn nicht angegeben, wird der Standardkomprimierungsalgorithmus des Kernels verwendet. | Nicht festgelegt |
mmd.zram.size |
Die Größe des ZRAM-Geräts in Byte oder ein Prozentsatz der RAM-Größe des Geräts, z. B. 75%.
|
50% |
mmd.zram.writeback.enabled |
Gibt an, ob ZRAM-Writeback aktiviert werden soll. | false |
mmd.zram.writeback.device_size |
Die Größe des Writeback-Geräts in Byte oder als Prozentsatz der Datenpartition. Die tatsächliche Gerätegröße kann je nach verfügbarem Speicherplatz auf der Datenpartition angepasst werden. | 1073741824 (1 GiB) |
mmd.zram.writeback.min_free_space_mib |
Der minimale kostenlose Speicherplatz in MiB, der nach der Einrichtung des Writeback-Geräts verfügbar sein muss. | 1536 (1,5 GiB) |
mmd.zram.writeback.use_nr_tags_prop |
Wenn true, wird der Wert in mmd.zram.writeback.nr_tags verwendet, um die Warteschlangentiefe des Loop-Geräts zu konfigurieren, das ZRAM-Writeback unterstützt. Dies ist eine Problemumgehung für Situationen, in denen die SELinux-Richtlinie des Anbieters nicht so konfiguriert werden kann, dass mmd nr_tags des Blockgeräts, das /data unterstützt, direkt lesen kann.
|
false |
mmd.zram.writeback.nr_tags |
mmd.zram.writeback.use_nr_tags_prop ansehen. |
Nicht festgelegt |
mmd.zram.recompression.enabled |
Gibt an, ob die ZRAM-Neukomprimierungsfunktion aktiviert werden soll. | false |
mmd.zram.recompression.algorithm |
Sekundärer ZRAM-Recompressionsalgorithmus. | zstd |
Geräteeigenschaften pro ZRAM
Wenn mmd.zram.num_devices größer als 1 ist, können bestimmte Eigenschaften optional für jedes ZRAM-Gerät konfiguriert werden. Dazu muss die Eigenschaft auf einen durch Kommas getrennten Wert mit genau mmd.zram.num_devices Elementen festgelegt werden.
Zu den Eigenschaften gehören:
mmd.zram.sizemmd.zram.comp_algorithmmmd.zram.device_prioritymmd.zram.recompression.enabledmmd.zram.recompression.huge_idle.enabledmmd.zram.recompression.idle.enabledmmd.zram.recompression.huge.enabledmmd.zram.recompression.threshold_bytesmmd.zram.recompression.algorithmmmd.zram.writeback.device_sizemmd.zram.writeback.huge_idle.enabledmmd.zram.writeback.idle.enabledmmd.zram.writeback.huge.enabled
Einstellung der vorhandenen ZRAM-Einrichtung
swapon_all ist zwar weiterhin in Android verfügbar, um ZRAM und festplattenbasierten Swap-Speicher einzurichten, mmd ist jedoch der bevorzugte Ansatz für die ZRAM-Verwaltung, da die Konfiguration einfacher ist und erweiterte Funktionen wie die ZRAM-Neukomprimierung unterstützt werden.
Wenn die mmd-ZRAM-Einrichtung durch mmd.zram.enabled aktiviert wird:
- Die ZRAM-Einrichtung in der
swapon_all-Implementierung wird zu einem No-Op. - Vorhandene ZRAM-Konfigurationen wie
config_zramWritebackin der Overlay-Dateiconfig.xmlundro.zram.*-Writeback-Systemeigenschaften werden ignoriert.
ZRAM-Wartungseinstellungen
Die ZRAM-Wartung sollte sofort funktionieren. Sie können sie jedoch mit den Systemattributen in diesem Abschnitt weiter optimieren.
ZRAM-Wartungsplanung
Mit diesen Eigenschaften wird gesteuert, wie und wann ZRAM-Wartungsaufgaben von system_server geplant werden.
| Attribut | Verwenden | Standard |
|---|---|---|
mm.zram.maintenance.first_delay_seconds |
Die Verzögerung, bevor die erste ZRAM-Wartung gestartet wird. | 3600 (1 Stunde) |
mm.zram.maintenance.periodic_delay_seconds |
Die Verzögerung zwischen aufeinanderfolgenden ZRAM-Wartungsplanungen. | 3600 (1 Stunde) |
mm.zram.maintenance.require_device_idle |
Gibt an, ob die ZRAM-Wartung nur initiiert werden soll, wenn das Gerät inaktiv ist. | true |
mm.zram.maintenance.require_battery_not_low |
Gibt an, ob der Akku nicht leer sein muss, bevor die ZRAM-Wartung gestartet wird. | true |
ZRAM-Writeback-Richtlinie
Die folgenden Parameter steuern, wann und welcher Speichertyp auf das Sicherungsgerät geschrieben wird:
| Attribut | Verwenden | Standard |
|---|---|---|
mmd.zram.writeback.backoff_seconds |
Die Backoff-Zeit seit dem letzten Writeback-Vorgang. | 600 (10 Minuten) |
mmd.zram.writeback.min_idle_seconds |
Wird mit mmd.zram.writeback.max_idle_seconds kombiniert, um das Alter im Leerlauf für eine Seite zu berechnen, damit sie basierend auf dem Anteil der Speichernutzung für das Zurückschreiben infrage kommt. Das berechnete Alter im Leerlauf wird exponentiell zwischen den beiden Parametern interpoliert, um den Aufwand zu minimieren, wenn der Arbeitsspeicher nicht ausgelastet ist.
|
72000 (20 Stunden) |
mmd.zram.writeback.max_idle_seconds |
Maximale Anzahl an Sekunden, die für die dynamische Berechnung des Alters von inaktiven Seiten basierend auf der Arbeitsspeicherauslastung verwendet werden. | 90000 (25 Stunden) |
mmd.zram.writeback.huge.enabled |
Gibt an, ob der HUGE-Seitenrückschreibevorgang aktiviert werden soll. |
false |
mmd.zram.writeback.idle.enabled |
Gibt an, ob der IDLE-Seitenrückschreibevorgang aktiviert werden soll. |
true |
mmd.zram.writeback.huge_idle.enabled |
Gibt an, ob der HUGE_IDLE-Seitenrückschreibevorgang aktiviert werden soll. |
true |
mmd.zram.writeback.min_bytes |
Mindestanzahl an Byte, die in einer Runde des Leerlauf-Writeback zurückgeschrieben werden müssen. | 5242880 (5 MiB) |
mmd.zram.writeback.max_bytes |
Maximale Anzahl von Byte, die in einer Runde des Leerlauf-Writeback zurückgeschrieben werden sollen. | 314572800 (300 MiB) |
mmd.zram.writeback.max_bytes_per_day |
Maximale Anzahl von Byte, die in einem Zeitraum von 24 Stunden zurückgeschrieben werden sollen. | 25769803776 (24 GiB) |
mmd.zram.writeback.limit.enabled |
Gibt an, ob das Tagesbudgetlimit für den Rückschreibevorgang berücksichtigt werden soll. | true |
Richtlinie für die ZRAM-Neukomprimierung
Die folgenden Parameter steuern, wann und welcher Arbeitsspeicher rekomprimiert wird:
| Attribut | Verwenden | Standard |
|---|---|---|
mmd.zram.recompression.backoff_seconds |
Die Backoff-Zeit seit der letzten Neukomprimierung. | 1800 (30 Minuten) |
mmd.zram.recompression.min_idle_seconds |
Wird mit mmd.zram.recompression.max_idle_seconds kombiniert, um das inaktive Alter für eine Seite zu berechnen, damit sie basierend auf dem Anteil der Arbeitsspeichernutzung für die Neukomprimierung infrage kommt. Das berechnete Alter im Leerlauf wird exponentiell zwischen den beiden Parametern interpoliert, um den Aufwand zu minimieren, wenn der Arbeitsspeicher nicht ausgelastet ist.
|
7200 (2 Stunden) |
mmd.zram.recompression.max_idle_seconds |
Maximale Anzahl an Sekunden, die für die dynamische Berechnung des Alters von inaktiven Seiten verwendet werden. | 14400 (4 Stunden) |
mmd.zram.recompression.threshold_bytes |
Die Mindestgröße in Byte von ZRAM-Seiten, die für die erneute Komprimierung infrage kommen. | 1024 (1 KiB) |
mmd.zram.recompression.huge.enabled |
Gibt an, ob die HUGE-Seitenrekomprimierung aktiviert werden soll. |
true |
mmd.zram.recompression.idle.enabled |
Gibt an, ob die IDLE-Seitenrekomprimierung aktiviert werden soll. |
true |
mmd.zram.recompression.huge_idle.enabled |
Gibt an, ob die HUGE_IDLE-Seitenrekomprimierung aktiviert werden soll. |
true |
ZRAM-Tracking von inaktiven Seiten
mmd Bei der ZRAM-Wartung werden ZRAM-Seiten als inaktiv markiert, je nachdem, wie lange der letzte Zugriff auf sie zurückliegt. Für diese Funktion müssen die Kernelkonfigurationen CONFIG_ZRAM_TRACK_ENTRY_ACTIME oder CONFIG_ZRAM_MEMORY_TRACKING aktiviert sein. CONFIG_ZRAM_TRACK_ENTRY_ACTIME ist in GKI-Kerneln ab Version 6.18 standardmäßig aktiviert. Bei früheren Kernels ist der Arbeitsspeicheraufwand höher und die Funktion ist nicht standardmäßig aktiviert.
Wenn die Kernelkonfiguration nicht aktiviert ist, wird für die mmd-ZRAM-Wartung eine Software-Ersatzlogik verwendet, um inaktive ZRAM-Seiten zu verfolgen:
Markieren Sie alle ZRAM-Seiten als inaktiv, wenn
mmdgestartet wird.Überspringe die nächsten ZRAM-Wartungen, bis die erforderliche Backoff-Periode abgelaufen ist.
ZRAM-Writeback oder erneutes Komprimieren von inaktiven Seiten. Wenn aufgrund von Writeback-Beschränkungen noch inaktive Seiten vorhanden sind, schreibt
mmddie Seiten bei der nächsten Wartung zurück, ohne neue Seiten als inaktiv zu markieren (Schritt 4 wird übersprungen).Wenn alle inaktiven Seiten zurückgeschrieben wurden, markieren Sie alle ZRAM-Seiten wieder als inaktiv und kehren Sie zu Schritt 2 zurück. Wenn ZRAM-Writeback deaktiviert ist, markiert
mmdalle ZRAM-Seiten als inaktiv, wenn die ZRAM-Neukomprimierung nach der Dauer der Inaktivität für die Neukomprimierung erfolgt.
Anleitung zur Fehlerbehebung und Validierung
Mit den folgenden Validierungsschritten und Verfahren zur Fehlerbehebung können Sie mmd- und ZRAM-Vorgänge überprüfen und diagnostizieren.
ZRAM-Einrichtung validieren
So prüfen Sie, ob mmd ZRAM während des Bootvorgangs erfolgreich konfiguriert hat:
Aktiven Komprimierungsalgorithmus und Festplattengröße prüfen:
cat /sys/block/zram0/comp_algorithm cat /sys/block/zram0/disksizePrüfen Sie die
mmd-Systemeigenschaften und den Status des ausgeführten Dienstes:getprop | grep mmd.zram dumpsys -l | grep mmd
ZRAM-Wartung und -Rückschreiben validieren
Prüfen Sie, ob die Wartungsaufgaben für ZRAM-Writeback und ‑Neukomprimierung funktionieren:
Status des zugrunde liegenden Blockgeräts prüfen:
cat /sys/block/zram0/bd_statPrüfen Sie die Effizienz der Neukomprimierung, indem Sie
/sys/block/zram0/mm_statbeobachten. Änderungen bei der Größe komprimierter Daten sollten nach Wartungszyklen sichtbar werden.
Per-Prozess-Writeback validieren
So können Sie prüfen, ob der prozessbezogene Writeback funktioniert:
- Prüfen Sie
adb logcat -s mmdauf erfolgreiche Writeback-Logs oder Fehlerdiagnosen.
Häufige Probleme und Diagnosen
Im Folgenden finden Sie einige häufige Fehlersituationen, die bei Nutzern auftreten können:
WritebackDailyLimitExceeded:Dieser Fehler weist darauf hin, dass das Kontingent fürmmd.zram.writeback.max_bytes_per_dayerreicht wurde. In diesem Fall pausiertmmdden Leerlauf-Writeback, bis das gleitende 24-Stunden-Fenster weiterläuft.Process prefetch or writeback failed:Dieser Fehler kann in Logcat beobachtet werden, wenn ein ioctl fehlschlägt. Häufige Ursachen:EBADFoderESRCH: Der Zielprozess wurde beendet, bevormmddiepidfdan den Kernel senden konnte.ENOSPC: Die Partition des zugrunde liegenden Speichers ist voll oder die Warteschlange des Loop-Geräts ist leer.
- ZRAM nicht eingerichtet:Wenn
mmdZRAM beim Booten nicht konfigurieren kann, liegt das möglicherweise daran, dass Legacy-swapon_all- oder Vendor-Init-Scripts/dev/block/zram0gesperrt haben, bevormmdausgeführt werden konnte.