Daemon di gestione della memoria

Android 17 e versioni successive supportano il daemon di gestione della memoria (mmd), un daemon di sistema, che gestisce la configurazione, i parametri regolabili e le attività di manutenzione di swap o ZRAM in corso.

Sfondo

Prima dell'introduzione di mmd, le configurazioni ZRAM di Android erano frammentate e offrivano una personalizzazione limitata. mmd risolve questo problema centralizzando la gestione di ZRAM, consentendo una logica di configurazione più sofisticata e semplificando l'aggiunta di nuove funzionalità e miglioramenti dell'architettura. mmd stabilisce inoltre una chiara separazione delle responsabilità tra il processo system_server basato su Java e la gestione della memoria o dello swap a livello di kernel.

Architettura e gestione di ZRAM

Al termine dell'avvio (ovvero quando sys.boot_completed=1), mmd_setup tenta di configurare ZRAM con i parametri specificati. Al termine della configurazione di ZRAM, il sistema attiva il servizio mmd, che gestisce le attività di manutenzione in corso.

Con il progetto mmd, le operazioni di manutenzione vengono avviate da system_server inviando richieste Binder a mmd utilizzando l'interfaccia IMmd. mmd gestisce le attività di manutenzione di esecuzione del writeback ZRAM, ricompressione e writeback per processo in base al proprio motore di criteri interno. Sia la pianificazione da ActivityManagerService sia le norme di manutenzione ZRAM possono essere configurate utilizzando le proprietà di sistema.

Integrazione del server di sistema (system_server)

Il processo system_server basato su Java determina quando viene richiamato mmd. La procedura separa le pulizie di manutenzione globali dalle ottimizzazioni mirate della memoria per app.

Manutenzione normale della post-elaborazione

La manutenzione globale di ZRAM è gestita da ActivityManagerService utilizzando com.android.server.memory.ZramMaintenance.

zram-maintenance

Figura 1. Flusso di pianificazione della manutenzione di ZRAM.

  • Motore di pianificazione: ZramMaintenance registra un'attività periodica in background con JobScheduler di Android.
  • Vincoli del job:per evitare problemi di stuttering dell'interfaccia utente in primo piano o contese della CPU, il job è configurato in modo esplicito con setRequiresDeviceIdle(true) e setRequiresBatteryNotLow(true).
  • Attivazione del binder:quando lo scheduler attiva onStartJob(), system_server richiama mmd.doZramMaintenanceAsync(). Si tratta di una chiamata Binder asincrona unidirezionale; system_server non blocca l'attesa del completamento delle operazioni di manutenzione. mmd lo mette in coda in un thread di lavoro in background per eseguire la ricompressione e la riscrittura in sequenza.

Writeback per processo

L'eliminazione mirata della memoria per processo viene gestita da ActivityManagerService utilizzando com.android.server.am.CachedAppOptimizer.

mmd-writeback

Figura 2. Flusso di writeback per processo di mmd.

Quando un processo passa a uno stato memorizzato nella cache in background, ActivityManager esegue la compattazione della memoria. Se un'interruzione per memoria insufficiente del processo fosse visibile all'utente, ovvero se il processo ospita un'attività e se il writeback per processo di ZRAM portasse il footprint della memoria del processo quasi a zero, il sistema esegue i seguenti passaggi:

  1. Dopo la compattazione, CachedAppOptimizer pubblica un messaggio ritardato (ZRAM_WRITEBACK_MSG) al suo gestore di compattazione interno (ritardato di mZramWritebackWaitSeconds).
  2. Quando il ritardo scade, ActivityManager apre un descrittore di file di processo sicuro pidfd.
  3. Il server di sistema chiama mmd.asyncWritebackProcessZramMemory(pfd, callback).
  4. mmd esegue l'ioctl di writeback per processo e invia una risposta utilizzando IMmdProcessWritebackCallback. Se l'operazione va a buon fine, ActivityManager contrassegna il record del processo (setIsZramWrittenBack(app, true)) per aumentare il oom_score_adj del processo e registra le metriche in FrameworkStatsLog.ZRAM_WRITEBACK_EVENT.

Prefetch per processo

Quando un utente riavvia un'app precedentemente memorizzata nella cache (sbloccata a causa di UNFREEZE_REASON_ACTIVITY), ActivityManager riduce al minimo la latenza di avvio dell'app causata da errori di pagina gravi dall'archiviazione di backup:

  1. CachedAppOptimizer intercetta l'evento di riattivazione e richiama prefetchZram(app).
  2. Il server di sistema invia l'intent pidfd dell'app tramite Binder utilizzando mmd.asyncPrefetchProcessZramMemory(pfd). mmd emette l'ioctl ZRAM_ANDROID_IOC_PROCESS_PREFETCH, istruendo il kernel a precaricare in modo asincrono le pagine scambiate nella RAM mentre il thread dell'interfaccia utente principale dell'app è in fase di inizializzazione.

Panoramica delle attività di manutenzione e post-elaborazione

Questa sezione descrive le operazioni di manutenzione in background e le attività di post-elaborazione eseguite da mmd per ottimizzare lo spazio di swap e la memoria di sistema.

Manutenzione in mmd

In mmd, la manutenzione si riferisce alle operazioni di manutenzione pianificate in background che ottimizzano l'utilizzo dello spazio di swap e della memoria fisica senza influire sulle prestazioni in primo piano degli utenti attivi. Anziché eseguire scansioni continue e sincrone (che causerebbero riattivazioni della CPU e problemi di UI), la manutenzione viene eseguita in modo asincrono:

  1. system_server attiva periodicamente doZramMaintenanceAsync() in Binder.

  2. mmd inserisce la richiesta in una coda di lavoro in background LowPrioWorkItem::ZramMaintenance.

  3. In mmd è presente un singolo thread worker che gestisce sia una coda a priorità elevata sia una coda a priorità bassa. Gli elementi di lavoro ad alta priorità (come il prefetch per processo) vengono elaborati per primi e possono avere la precedenza sugli elementi di lavoro a bassa priorità. La manutenzione e il writeback per processo funzionano come elementi di lavoro a bassa priorità. Quando viene estratto, il thread di lavoro esegue in sequenza due operazioni di manutenzione principali:

    • Ricompressione ZRAM:esamina le pagine di swap esistenti e ricomprime le pagine inattive utilizzando un algoritmo di compressione secondaria con un rapporto più elevato, ad esempio zstd.

    • Scrittura differita ZRAM: esegue la scansione delle pagine inattive e le rimuove completamente dalla RAM per eseguire il backup dello spazio di archiviazione flash di un dispositivo loop da un file su /data.

Attività di post-elaborazione in ZRAM

Nel modulo ZRAM del kernel Linux e nell'architettura mmd, le attività di post-elaborazione sono le trasformazioni asincrone applicate alle pagine di memoria dopo che sono già state scambiate dai percorsi di recupero standard del kernel (kswapd o compattazione).

Quando una pagina viene inizialmente sostituita, il sistema dà la priorità alla velocità: utilizza un algoritmo di compressione primario veloce (come lz4) e memorizza la pagina compressa nella RAM. Tuttavia, nel tempo, molte pagine di swap diventano fredde o inattive, ad esempio le app memorizzate nella cache in background che non vengono riprese per ore. Lasciare le pagine fredde nella ZRAM veloce e leggermente compressa è inefficiente.

Pipeline di post-elaborazione

mmd implementa un ciclo di vita di post-elaborazione multifase per ottimizzare queste pagine:

mmd-page-lifecycle

Figura 3. mmd ciclo di vita della pagina.

  1. Fase 1: sostituzione iniziale (compressione rapida): la memoria viene recuperata tramite kswapd o la compattazione delle app. In genere, questo primo recupero viene eseguito utilizzando un algoritmo di compressione rapida come lz4 e i contenuti vengono memorizzati nella RAM.

  2. Fase 2: contrassegno di inattività (invecchiamento e monitoraggio): mmd il monitoraggio dell'inattività accede al monitoraggio della memoria del kernel (CONFIG_ZRAM_TRACK_ENTRY_ACTIME) o utilizza il proprio indicatore di inattività software per monitorare per quanto tempo le pagine sono rimaste invariate.

  3. Fase 3: post-elaborazione 1 - ricompressione (recupero in memoria): Le pagine che raggiungono l'età di inattività della ricompressione (da min_idle_seconds a max_idle_seconds) vengono ricompresse. mmd scrive a /sys/block/zram0/recompress per indicare al kernel di decomprimere la pagina lz4 e ricomprimerla utilizzando zstd. In questo modo viene recuperata la RAM fisica senza usura della scrittura flash.

  4. Fase 4: post-elaborazione 2 - writeback (rimozione nell'archivio flash): se la pressione della memoria continua e le pagine raggiungono l'età di inattività di writeback (in genere 20 ore o più), mmd attiva il writeback. mmd scrive su /sys/block/zram0/idle e /sys/block/zram0/writeback per espellere la pagina compressa interamente dalla RAM all'archivio flash di backup.

Configurazione dell'installazione di ZRAM

mmd carica ed elabora le seguenti proprietà di configurazione di ZRAM:

Proprietà Usa Predefinito
mmd.zram.enabled Indica se è attiva la configurazione mmd ZRAM. false
mmd.zram.num_devices Il numero di dispositivi ZRAM da configurare. Per un numero N, i dispositivi da zram0 a zram<N-1> devono essere presenti prima che il sistema imposti sys.boot_completed=1. Le proprietà dell'elenco dei dispositivi per ZRAM possono essere configurate in base al dispositivo. 1
mmd.zram.device_priority Valori di priorità da trasmettere quando chiami swapon. Non impostato
mmd.zram.comp_algorithm Algoritmo di compressione ZRAM. Se non specificato, viene utilizzato l'algoritmo di compressione predefinito del kernel. Non impostato
mmd.zram.size Dimensioni del dispositivo ZRAM in byte o percentuale delle dimensioni della RAM del dispositivo, ad esempio 75%. 50%
mmd.zram.writeback.enabled Se abilitare la riscrittura ZRAM. false
mmd.zram.writeback.device_size Le dimensioni del dispositivo di writeback in byte o la percentuale della partizione di dati. Le dimensioni effettive del dispositivo possono essere regolate in base allo spazio disponibile nella partizione dei dati. 1073741824 (1 GiB)
mmd.zram.writeback.min_free_space_mib Spazio libero minimo in MiB che deve essere disponibile dopo la configurazione del dispositivo di riscrittura. 1536 (1,5 GiB)
mmd.zram.writeback.use_nr_tags_prop Quando true, utilizza il valore in mmd.zram.writeback.nr_tags per configurare la profondità della coda di scrittura di ZRAM del dispositivo di loop. Questa è una soluzione alternativa per le situazioni in cui non è possibile configurare il criterio SELinux del fornitore per consentire a mmd di leggere direttamente nr_tags del dispositivo di blocco di backup /data. false
mmd.zram.writeback.nr_tags Leggi i mmd.zram.writeback.use_nr_tags_prop. Non impostato
mmd.zram.recompression.enabled Se abilitare la funzionalità di ricompressione ZRAM. false
mmd.zram.recompression.algorithm Algoritmo di ricompressione ZRAM secondario. zstd

Proprietà del dispositivo per ZRAM

Quando mmd.zram.num_devices è maggiore di uno, è possibile configurare facoltativamente proprietà specifiche in base al dispositivo ZRAM impostando la proprietà su un valore separato da virgole contenente esattamente mmd.zram.num_devices elementi. Queste proprietà includono:

  • mmd.zram.size
  • mmd.zram.comp_algorithm
  • mmd.zram.device_priority
  • mmd.zram.recompression.enabled
  • mmd.zram.recompression.huge_idle.enabled
  • mmd.zram.recompression.idle.enabled
  • mmd.zram.recompression.huge.enabled
  • mmd.zram.recompression.threshold_bytes
  • mmd.zram.recompression.algorithm
  • mmd.zram.writeback.device_size
  • mmd.zram.writeback.huge_idle.enabled
  • mmd.zram.writeback.idle.enabled
  • mmd.zram.writeback.huge.enabled

Ritiro della configurazione ZRAM esistente

Sebbene swapon_all sia ancora disponibile in Android per configurare ZRAM e lo spazio di swap basato su disco, mmd è l'approccio preferito per la gestione di ZRAM per una configurazione più semplice e funzionalità avanzate come la ricompressione ZRAM.

Quando la configurazione di mmd ZRAM è abilitata da mmd.zram.enabled:

  • La configurazione di ZRAM nell'implementazione swapon_all diventa un'operazione nulla.
  • Le configurazioni ZRAM esistenti, come config_zramWriteback nell'overlay config.xml e le proprietà di sistema di writeback ro.zram.*, vengono ignorate.

Parametri regolabili di manutenzione ZRAM

La manutenzione di ZRAM dovrebbe funzionare immediatamente e puoi perfezionarla ulteriormente utilizzando le proprietà di sistema in questa sezione.

Pianificazione della manutenzione di ZRAM

Queste proprietà controllano come e quando le attività di manutenzione di ZRAM vengono pianificate da system_server.

Proprietà Usa Predefinito
mm.zram.maintenance.first_delay_seconds Il ritardo prima dell'avvio della prima manutenzione di ZRAM. 3600 (1 ora)
mm.zram.maintenance.periodic_delay_seconds Il ritardo tra la pianificazione della manutenzione ZRAM successiva. 3600 (1 ora)
mm.zram.maintenance.require_device_idle Se avviare la manutenzione di ZRAM solo quando il dispositivo è inattivo. true
mm.zram.maintenance.require_battery_not_low Se richiedere che la batteria non sia scarica prima di avviare la manutenzione di ZRAM. true

Policy di writeback di ZRAM

I seguenti parametri controllano quando e quale tipo di memoria viene scritto sul dispositivo di archiviazione:

Proprietà Usa Predefinito
mmd.zram.writeback.backoff_seconds Tempo di backoff dall'ultima operazione di writeback. 600 (10 minuti)
mmd.zram.writeback.min_idle_seconds Combinato con mmd.zram.writeback.max_idle_seconds per calcolare l'età di inattività di una pagina per poter essere idonea al writeback in base alla frazione di utilizzo della memoria. L'età di inattività calcolata viene interpolata in modo esponenziale tra i due parametri per ridurre al minimo il lavoro quando non è presente una pressione sulla memoria. 72000 (20 ore)
mmd.zram.writeback.max_idle_seconds Numero massimo di secondi utilizzati per calcolare dinamicamente l'età della pagina inattiva in base all'utilizzo della memoria. 90000 (25 ore)
mmd.zram.writeback.huge.enabled Se abilitare il writeback della pagina HUGE. false
mmd.zram.writeback.idle.enabled Se abilitare il writeback della pagina IDLE. true
mmd.zram.writeback.huge_idle.enabled Se abilitare il writeback della pagina HUGE_IDLE. true
mmd.zram.writeback.min_bytes Numero minimo di byte da riscrivere in un ciclo di riscrittura inattiva. 5242880 (5 MiB)
mmd.zram.writeback.max_bytes Il numero massimo di byte da riscrivere in un ciclo di riscrittura inattiva. 314572800 (300 MiB)
mmd.zram.writeback.max_bytes_per_day Il numero massimo di byte da riscrivere in un periodo di 24 ore. 25769803776 (24 GiB)
mmd.zram.writeback.limit.enabled Indica se attivare la contabilizzazione del limite di budget di writeback giornaliero. true

Policy di ricompressione ZRAM

I seguenti parametri controllano quando e quale tipo di memoria viene ricompresso:

Proprietà Usa Predefinito
mmd.zram.recompression.backoff_seconds Tempo di backoff dall'ultima ricompressione. 1800 (30 minuti)
mmd.zram.recompression.min_idle_seconds Insieme a mmd.zram.recompression.max_idle_seconds per calcolare l'età di inattività di una pagina per poterla ricomprimere in base alla frazione di utilizzo della memoria. L'età di inattività calcolata viene interpolata in modo esponenziale tra i due parametri per ridurre al minimo il lavoro quando non è presente pressione sulla memoria. 7200 (2 ore)
mmd.zram.recompression.max_idle_seconds Il numero massimo di secondi utilizzato per calcolare dinamicamente l'età della pagina inattiva. 14400 (4 ore)
mmd.zram.recompression.threshold_bytes Dimensioni minime in byte delle pagine ZRAM considerate per la ricompressione. 1024 (1 KiB)
mmd.zram.recompression.huge.enabled Se abilitare la ricompressione della pagina HUGE. true
mmd.zram.recompression.idle.enabled Se abilitare la ricompressione della pagina IDLE. true
mmd.zram.recompression.huge_idle.enabled Se abilitare la ricompressione della pagina HUGE_IDLE. true

Monitoraggio delle pagine inattive ZRAM

mmd La manutenzione di ZRAM contrassegna le pagine ZRAM come inattive in base al tempo trascorso dall'ultimo accesso. Questa funzionalità richiede l'abilitazione delle configurazioni del kernel CONFIG_ZRAM_TRACK_ENTRY_ACTIME o CONFIG_ZRAM_MEMORY_TRACKING. CONFIG_ZRAM_TRACK_ENTRY_ACTIME è abilitato per impostazione predefinita sui kernel GKI 6.18 e versioni successive. Nei kernel precedenti, ha un overhead di memoria e non è abilitato per impostazione predefinita.

Se la configurazione del kernel non è attivata, la manutenzione di mmd ZRAM ricorre a una logica di sostituzione software per monitorare le pagine ZRAM inattive:

  1. Contrassegna tutte le pagine ZRAM come inattive all'avvio di mmd.

  2. Salta le successive manutenzioni di ZRAM finché non è trascorso il periodo di backoff richiesto.

  3. ZRAM writeback o ricompressione delle pagine inattive. Se rimangono pagine inattive a causa dei limiti di writeback, mmd continua a scrivere le pagine durante la manutenzione successiva senza contrassegnare le nuove pagine come inattive (saltando il passaggio 4).

  4. Se tutte le pagine inattive vengono riscritte, contrassegna di nuovo tutte le pagine ZRAM come inattive e torna al passaggio 2. Se il writeback di ZRAM è disattivato, mmd contrassegna tutte le pagine ZRAM come inattive quando la ricompressione ZRAM avviene dopo la durata di inattività della ricompressione.

Guida alla risoluzione dei problemi e alla convalida

Segui i passaggi di convalida e le procedure di risoluzione dei problemi riportati di seguito per verificare e diagnosticare le operazioni mmd e ZRAM.

Convalida la configurazione di ZRAM

Per verificare che mmd abbia configurato correttamente ZRAM durante l'avvio:

  1. Controlla l'algoritmo di compressione attivo e le dimensioni del disco:

    cat /sys/block/zram0/comp_algorithm
    cat /sys/block/zram0/disksize
    
  2. Verifica le proprietà di sistema mmd e lo stato del servizio in esecuzione:

    getprop | grep mmd.zram
    dumpsys -l | grep mmd
    

Convalida la manutenzione e il writeback di ZRAM

Verifica che le attività di manutenzione di writeback e ricompressione di ZRAM funzionino:

  1. Controlla lo stato del dispositivo di blocco di supporto:

    cat /sys/block/zram0/bd_stat
    
  2. Verifica l'efficienza della ricompressione monitorando /sys/block/zram0/mm_stat. Le modifiche alle dimensioni dei dati compressi dovrebbero essere visualizzate dopo i cicli di manutenzione.

Convalida il writeback per processo

Per convalidare il funzionamento del writeback per processo, puoi utilizzare quanto segue:

  • Controlla adb logcat -s mmd per i log di writeback riusciti o la diagnostica degli errori.

Problemi comuni e diagnostica

Di seguito sono riportate situazioni di errore comuni in cui l'utente potrebbe imbattersi:

  • WritebackDailyLimitExceeded: questo errore indica che è stata raggiunta la quota di mmd.zram.writeback.max_bytes_per_day. Quando ciò si verifica, mmd mette in pausa la riscrittura inattiva finché non avanza la finestra mobile di 24 ore.
  • Process prefetch or writeback failed: questo errore può essere osservato in logcat quando un ioctl non va a buon fine. Tra le cause più comuni:
    • EBADF o ESRCH: il processo di destinazione è terminato prima che mmd potesse inviare pidfd al kernel.
    • ENOSPC: la partizione di archiviazione di backup è piena o la coda del dispositivo di loop è esaurita.
  • ZRAM non configurato: se mmd non riesce a configurare ZRAM all'avvio, il problema potrebbe essere dovuto al fatto che gli script di inizializzazione swapon_all o del fornitore legacy hanno bloccato /dev/block/zram0 prima che mmd potesse essere eseguito.