Android 17 et versions ultérieures sont compatibles avec le daemon de gestion de la mémoire (mmd), un daemon système qui gère la configuration du daemon, les paramètres réglables et les tâches de maintenance continues d'échange ou de ZRAM.
Arrière-plan
Avant l'introduction de mmd, les configurations ZRAM d'Android étaient fragmentées et offraient une personnalisation limitée. mmd résout ce problème en centralisant la gestion de ZRAM, ce qui permet une logique de configuration plus sophistiquée et simplifie l'ajout de nouvelles fonctionnalités et d'améliorations architecturales.
mmd établit également une séparation claire des préoccupations entre le processus system_server basé sur Java et la gestion de la mémoire ou du swap au niveau du noyau.
Architecture et gestion de ZRAM
Une fois le démarrage terminé (c'est-à-dire lorsque sys.boot_completed=1), mmd_setup tente de configurer ZRAM avec les paramètres spécifiés. Une fois la configuration de ZRAM terminée, le système active le service mmd qui gère les tâches de maintenance en cours.
Avec le projet mmd, les opérations de maintenance sont initiées à partir de system_server en envoyant des requêtes Binder à mmd à l'aide de l'interface IMmd.
mmd gère les tâches de maintenance liées à l'écriture différée ZRAM, à la recompression et à l'écriture différée par processus en fonction de son propre moteur de règles internes. La planification à partir de ActivityManagerService et les règles de maintenance ZRAM peuvent être configurées à l'aide des propriétés système.
Intégration du serveur système (system_server)
Le processus system_server basé sur Java détermine quand mmd est appelé. Le processus sépare les opérations de maintenance globales des optimisations de mémoire ciblées par application.
Maintenance normale du post-traitement
La maintenance globale de ZRAM est gérée par ActivityManagerService à l'aide de com.android.server.memory.ZramMaintenance.

Figure 1. Flux de planification de la maintenance ZRAM.
- Moteur de planification :
ZramMaintenanceenregistre un job périodique en arrière-plan avecJobSchedulerd'Android. - Contraintes de tâche : pour éviter les saccades de l'UI au premier plan ou la contention du processeur, la tâche est explicitement configurée avec
setRequiresDeviceIdle(true)etsetRequiresBatteryNotLow(true). - Déclenchement du binder : lorsque le planificateur déclenche
onStartJob(),system_serverappellemmd.doZramMaintenanceAsync(). Il s'agit d'un appel Binder asynchrone unidirectionnel.system_serverne bloque pas l'attente de la fin des opérations de maintenance.mmdmet cette opération en file d'attente sur un thread de worker en arrière-plan pour effectuer la recompression et la réécriture de manière séquentielle.
Réécriture par processus
L'éviction ciblée de la mémoire par processus est gérée par ActivityManagerService à l'aide de com.android.server.am.CachedAppOptimizer.

Figure 2 : Flux de réécriture par processus MMD.
Lorsqu'un processus passe à un état mis en cache en arrière-plan, ActivityManager effectue une compaction de la mémoire. Si un plantage dû à une faible mémoire du processus est visible par l'utilisateur (c'est-à-dire que le processus héberge une activité) et si la réécriture ZRAM par processus ramènerait l'espace mémoire utilisé du processus à presque zéro, le système procède comme suit :
- Après la compaction,
CachedAppOptimizerpublie un message différé (ZRAM_WRITEBACK_MSG) à son gestionnaire de compaction interne (différé demZramWritebackWaitSeconds). - Une fois le délai expiré, ActivityManager ouvre un descripteur de fichier de processus sécurisé
pidfd. - Le serveur système appelle
mmd.asyncWritebackProcessZramMemory(pfd, callback). mmdexécute l'ioctl de réécriture par processus et renvoie des informations à l'aide deIMmdProcessWritebackCallback. Si l'opération réussit, ActivityManager signale l'enregistrement du processus (setIsZramWrittenBack(app, true)) pour améliorer leoom_score_adjdu processus et enregistre les métriques dansFrameworkStatsLog.ZRAM_WRITEBACK_EVENT.
Préfetche par processus
Lorsqu'un utilisateur relance une application précédemment mise en cache (décongelée en raison de UNFREEZE_REASON_ACTIVITY), ActivityManager réduit la latence de démarrage de l'application causée par les principaux défauts de page du stockage de sauvegarde :
CachedAppOptimizerintercepte l'événement de déblocage et appelleprefetchZram(app).- Le serveur système distribue le
pidfdde l'application sur Binder à l'aide demmd.asyncPrefetchProcessZramMemory(pfd).mmdémet l'ioctlZRAM_ANDROID_IOC_PROCESS_PREFETCH, en demandant au noyau de précharger de manière asynchrone les pages permutées dans la RAM pendant l'initialisation du thread d'UI principal de l'application.
Présentation des tâches de maintenance et de post-traitement
Cette section décrit les opérations de maintenance en arrière-plan et les tâches de post-traitement que mmd exécute pour optimiser l'espace d'échange et la mémoire système.
Maintenance en mmd
Dans mmd, le terme maintenance fait référence aux opérations de maintenance planifiées en arrière-plan qui optimisent l'utilisation de l'espace d'échange et de la mémoire physique sans affecter les performances au premier plan des utilisateurs actifs. Au lieu d'effectuer des balayages synchrones continus (qui entraîneraient de graves réveils du processeur et des à-coups dans l'UI), la maintenance est effectuée de manière asynchrone :
system_serverdéclenche périodiquementdoZramMaintenanceAsync()dans Binder.mmdplace la requête dans une file d'attente de tâches en arrière-planLowPrioWorkItem::ZramMaintenance.mmdcomporte un seul thread de nœud de calcul qui gère à la fois une file d'attente de haute priorité et une file d'attente de basse priorité. Les éléments de travail à priorité élevée (comme la prélecture par processus) sont traités en premier et peuvent prendre le pas sur les éléments de travail à faible priorité. La maintenance et l'écriture différée par processus fonctionnent comme des éléments de travail de faible priorité. Lorsqu'il est dépilé, le thread de travail exécute séquentiellement deux opérations de maintenance principales :Recompression ZRAM : parcourt les pages de swap existantes et recompressent les pages inactives à l'aide d'un algorithme de compression secondaire à rapport plus élevé, par exemple
zstd.Réécriture ZRAM : analyse les pages inactives et les supprime entièrement de la RAM pour les stocker dans la mémoire flash de sauvegarde, un périphérique de boucle à partir d'un fichier sur
/data.
Tâches de post-traitement dans ZRAM
Dans le module ZRAM du noyau Linux et l'architecture mmd, les tâches de post-traitement sont les transformations asynchrones appliquées aux pages mémoire après qu'elles ont déjà été permutées par les chemins de récupération standards du noyau (kswapd ou compaction).
Lorsqu'une page est initialement supprimée, le système privilégie la vitesse : il utilise un algorithme de compression primaire rapide (comme lz4) et stocke la page compressée dans la RAM. Toutefois, au fil du temps, de nombreuses pages permutées deviennent froides ou inactives (par exemple, les applications mises en cache en arrière-plan qui ne sont pas reprises pendant des heures). Il est inefficace de laisser des pages froides dans la ZRAM rapide et légèrement compressée.
Pipeline de post-traitement
mmd implémente un cycle de vie de post-traitement en plusieurs étapes pour optimiser ces pages :

Figure 3. cycle de vie de la page mmd.
Étape 1 : Échange initial (compression rapide) : la mémoire est d'abord récupérée par le biais de kswapd ou de la compaction d'application. En règle générale, cette première récupération est effectuée à l'aide d'un algorithme de compression rapide tel que
lz4, et le contenu est stocké dans la RAM.Étape 2 : Marquage de l'inactivité (vieillissement et suivi) : le suivi de l'inactivité
mmdaccède au suivi de la mémoire du noyau (CONFIG_ZRAM_TRACK_ENTRY_ACTIME) ou utilise son marqueur d'inactivité logicielle pour suivre la durée pendant laquelle les pages sont restées inutilisées.Étape 3 : Post-traitement 1 – Recompression (récupération en mémoire) : Les pages qui atteignent l'âge d'inactivité de recompression (de
min_idle_secondsàmax_idle_seconds) sont recompressées.mmdécrit dans/sys/block/zram0/recompresspour demander au noyau de décompresser la pagelz4et de la recompresser à l'aide dezstd. Cela permet de récupérer la RAM physique sans entraîner d'usure de l'écriture flash.Étape 4 : Post-traitement 2 – Écriture différée (éviction vers le stockage flash) : si la pression sur la mémoire persiste et que les pages atteignent l'âge d'inactivité d'écriture différée (généralement 20 heures ou plus),
mmddéclenche l'écriture différée.mmdécrit dans/sys/block/zram0/idleet/sys/block/zram0/writebackpour évincer complètement la page compressée de la RAM vers le stockage flash de sauvegarde.
Configuration de ZRAM
mmd charge et traite les propriétés de configuration ZRAM suivantes :
| Propriété | Utiliser | Par défaut |
|---|---|---|
mmd.zram.enabled |
Indique si la configuration ZRAM mmd est activée. |
false |
mmd.zram.num_devices |
Nombre d'appareils ZRAM à configurer. Pour un nombre N, les appareils zram0 à zram<N-1> doivent être présents avant que le système ne définisse sys.boot_completed=1.
Les propriétés de la liste des appareils ZRAM peuvent être configurées individuellement.
|
1 |
mmd.zram.device_priority |
Valeurs de priorité à transmettre lors de l'appel de swapon. |
Non défini |
mmd.zram.comp_algorithm |
Algorithme de compression ZRAM. Si aucun algorithme n'est spécifié, l'algorithme de compression par défaut du noyau est utilisé. | Non défini |
mmd.zram.size |
Taille de l'appareil ZRAM en octets ou pourcentage de la taille de la RAM de l'appareil (par exemple, 75%).
|
50% |
mmd.zram.writeback.enabled |
Indique si le writeback ZRAM doit être activé. | false |
mmd.zram.writeback.device_size |
Taille du périphérique de réécriture en octets ou en pourcentage de la partition de données. La taille réelle de l'appareil peut être ajustée en fonction de l'espace disponible sur la partition de données. | 1073741824 (1 Gio) |
mmd.zram.writeback.min_free_space_mib |
Espace libre minimal en Mio qui doit être disponible après la configuration du périphérique de réécriture. | 1536 (1,5 Gio) |
mmd.zram.writeback.use_nr_tags_prop |
Lorsque true, utilise la valeur dans mmd.zram.writeback.nr_tags pour configurer la profondeur de file d'attente de l'écriture différée ZRAM de sauvegarde du périphérique de boucle. Il s'agit d'une solution de contournement pour les situations où la règle SELinux du fournisseur ne peut pas être configurée pour permettre à mmd de lire directement nr_tags de la sauvegarde du périphérique de bloc /data.
|
false |
mmd.zram.writeback.nr_tags |
Consultez les mmd.zram.writeback.use_nr_tags_prop. |
Non défini |
mmd.zram.recompression.enabled |
Indique s'il faut activer la fonctionnalité de recompression ZRAM. | false |
mmd.zram.recompression.algorithm |
Algorithme de recompression ZRAM secondaire. | zstd |
Propriétés des appareils par ZRAM
Lorsque mmd.zram.num_devices est supérieur à un, des propriétés spécifiques peuvent éventuellement être configurées pour chaque appareil ZRAM en définissant la propriété sur une valeur séparée par des virgules contenant exactement mmd.zram.num_devices éléments.
Ces propriétés incluent :
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
Abandon de la configuration ZRAM existante
Bien que swapon_all soit toujours disponible dans Android pour configurer l'espace d'échange ZRAM et basé sur le disque, mmd est l'approche privilégiée pour la gestion de ZRAM, car elle facilite la configuration et offre des fonctionnalités avancées telles que la recompression ZRAM.
Lorsque la configuration ZRAM mmd est activée par mmd.zram.enabled :
- La configuration ZRAM dans l'implémentation
swapon_alldevient une opération sans effet. - Les configurations ZRAM existantes, telles que
config_zramWritebackdans le fichier de superpositionconfig.xmlet les propriétés système d'écriture différéero.zram.*, sont ignorées.
Paramètres réglables de maintenance ZRAM
La maintenance ZRAM devrait fonctionner immédiatement. Vous pouvez l'affiner davantage à l'aide des propriétés système de cette section.
Planification de la maintenance ZRAM
Ces propriétés contrôlent comment et quand les tâches de maintenance ZRAM sont planifiées par system_server.
| Propriété | Utiliser | Par défaut |
|---|---|---|
mm.zram.maintenance.first_delay_seconds |
Délai avant le lancement de la première maintenance ZRAM. | 3600 (1 heure) |
mm.zram.maintenance.periodic_delay_seconds |
Délai entre les planifications de maintenance ZRAM ultérieures. | 3600 (1 heure) |
mm.zram.maintenance.require_device_idle |
Indique s'il faut n'initier la maintenance ZRAM que lorsque l'appareil est inactif. | true |
mm.zram.maintenance.require_battery_not_low |
Indique s'il faut que la batterie ne soit pas faible avant de lancer la maintenance ZRAM. | true |
Stratégie de réécriture ZRAM
Les paramètres suivants contrôlent quand et quel type de mémoire est écrit sur le périphérique de stockage :
| Propriété | Utiliser | Par défaut |
|---|---|---|
mmd.zram.writeback.backoff_seconds |
Temps d'attente depuis la dernière opération d'écriture. | 600 (10 minutes) |
mmd.zram.writeback.min_idle_seconds |
Combiné à mmd.zram.writeback.max_idle_seconds pour calculer l'âge d'inactivité d'une page afin qu'elle soit éligible à la réécriture en fonction de la fraction d'utilisation de la mémoire. L'âge d'inactivité calculé est interpolé de manière exponentielle entre les deux paramètres pour minimiser le travail lorsque la mémoire n'est pas sous pression.
|
72000 (20 heures) |
mmd.zram.writeback.max_idle_seconds |
Nombre maximal de secondes utilisées pour calculer l'âge de la page inactive de manière dynamique en fonction de l'utilisation de la mémoire. | 90000 (25 heures) |
mmd.zram.writeback.huge.enabled |
Indique si la réécriture de la page HUGE doit être activée. |
false |
mmd.zram.writeback.idle.enabled |
Indique si la réécriture de la page IDLE doit être activée. |
true |
mmd.zram.writeback.huge_idle.enabled |
Indique si la réécriture de la page HUGE_IDLE doit être activée. |
true |
mmd.zram.writeback.min_bytes |
Nombre minimal d'octets à réécrire en une seule série de réécriture en cas d'inactivité. | 5242880 (5 Mio) |
mmd.zram.writeback.max_bytes |
Nombre maximal d'octets à réécrire en une seule fois lors de la réécriture en cas d'inactivité. | 314572800 (300 Mio) |
mmd.zram.writeback.max_bytes_per_day |
Nombre maximal d'octets à réécrire sur une période de 24 heures. | 25769803776 (24 Gio) |
mmd.zram.writeback.limit.enabled |
Indique si la comptabilisation de la limite de budget de réécriture quotidienne doit être activée. | true |
Règle de recompression ZRAM
Les paramètres suivants contrôlent le moment et le type de mémoire à recompresser :
| Propriété | Utiliser | Par défaut |
|---|---|---|
mmd.zram.recompression.backoff_seconds |
Temps d'attente depuis la dernière recompression. | 1800 (30 minutes) |
mmd.zram.recompression.min_idle_seconds |
Combiné à mmd.zram.recompression.max_idle_seconds pour calculer l'âge d'inactivité d'une page afin qu'elle soit éligible à la recompression en fonction de la fraction d'utilisation de la mémoire. L'âge d'inactivité calculé est interpolé de manière exponentielle entre les deux paramètres pour minimiser le travail lorsqu'il n'y a pas de pression sur la mémoire.
|
7200 (2 heures) |
mmd.zram.recompression.max_idle_seconds |
Nombre maximal de secondes utilisées pour calculer dynamiquement l'ancienneté de la page inactive. | 14400 (4 heures) |
mmd.zram.recompression.threshold_bytes |
Taille minimale en octets des pages ZRAM considérées pour la recompression. | 1024 (1 Kio) |
mmd.zram.recompression.huge.enabled |
Indique si la recompression de la page HUGE doit être activée. |
true |
mmd.zram.recompression.idle.enabled |
Indique si la recompression de la page IDLE doit être activée. |
true |
mmd.zram.recompression.huge_idle.enabled |
Indique si la recompression de la page HUGE_IDLE doit être activée. |
true |
Suivi des pages inactives de la ZRAM
mmd La maintenance de zRAM marque les pages zRAM comme inactives en fonction du temps écoulé depuis leur dernier accès. Cette fonctionnalité nécessite l'activation des configurations du noyau CONFIG_ZRAM_TRACK_ENTRY_ACTIME ou CONFIG_ZRAM_MEMORY_TRACKING. CONFIG_ZRAM_TRACK_ENTRY_ACTIME est activé par défaut sur les noyaux GKI 6.18 et versions ultérieures. Sur les anciens noyaux, il présente une surcharge de mémoire et n'est pas activé par défaut.
Si la configuration du noyau n'est pas activée, la maintenance mmd ZRAM revient à une logique de substitution logicielle pour suivre les pages ZRAM inactives :
Marquez toutes les pages ZRAM comme inactives lorsque
mmddémarre.Ignorer les prochaines maintenances ZRAM jusqu'à ce que la période de désactivation requise soit écoulée.
La zRAM réécrit ou recompressent les pages inactives. S'il reste des pages inactives en raison des limites de réécriture,
mmdcontinue de réécrire les pages lors de la prochaine maintenance sans marquer de nouvelles pages comme inactives (en ignorant l'étape 4).Si toutes les pages inactives sont réécrites, marquez à nouveau toutes les pages ZRAM comme inactives et revenez à l'étape 2. Si la réécriture ZRAM est désactivée,
mmdmarque toutes les pages ZRAM comme inactives lorsque la recompression ZRAM a lieu après la durée d'inactivité de recompression.
Conseils de dépannage et de validation
Suivez les étapes de validation et les procédures de dépannage ci-dessous pour vérifier et diagnostiquer les opérations mmd et ZRAM.
Valider la configuration de ZRAM
Pour vérifier que mmd a bien configuré ZRAM au démarrage :
Vérifiez l'algorithme de compression actif et la taille du disque :
cat /sys/block/zram0/comp_algorithm cat /sys/block/zram0/disksizeVérifiez les propriétés du système
mmdet l'état du service en cours d'exécution :getprop | grep mmd.zram dumpsys -l | grep mmd
Valider la maintenance et l'écriture différée de ZRAM
Vérifiez que les tâches de maintenance de réécriture et de recompression ZRAM fonctionnent :
Vérifiez l'état du périphérique de bloc de stockage :
cat /sys/block/zram0/bd_statVérifiez l'efficacité de la recompression en surveillant
/sys/block/zram0/mm_stat. Les modifications de la taille des données compressées devraient apparaître après les cycles de maintenance.
Valider le renvoi des données par processus
Les éléments suivants peuvent être utilisés pour valider le bon fonctionnement de la réécriture par processus :
- Consultez
adb logcat -s mmdpour obtenir les journaux d'écriture différée réussie ou les diagnostics d'échec.
Problèmes courants et diagnostics
Voici quelques situations d'erreur courantes que l'utilisateur peut rencontrer :
WritebackDailyLimitExceeded: cette erreur indique que le quotammd.zram.writeback.max_bytes_per_daya été atteint. Dans ce cas,mmdsuspend l'écriture différée inactive jusqu'à ce que la période de 24 heures avance.Process prefetch or writeback failed: cette erreur peut être observée dans logcat lorsqu'un ioctl échoue. Voici les causes les plus courantes :EBADFouESRCH: le processus cible s'est terminé avant quemmdpuisse envoyerpidfdau noyau.ENOSPC: la partition de stockage sous-jacente est pleine ou la file d'attente du périphérique de boucle est épuisée.
- ZRAM non configuré : si
mmdne parvient pas à configurer ZRAM au démarrage, cela peut être dû au fait que les anciens scripts d'initialisationswapon_allou ceux du fournisseur ont verrouillé/dev/block/zram0avant quemmdpuisse s'exécuter.