Daemon de protección de memoria de procesos

Android 17 y versiones posteriores admiten el daemon de protección de memoria de procesos (PMGD), que protege el estado del sistema y la experiencia del usuario administrando de forma proactiva el uso de memoria por proceso. El daemon mejora la estabilidad general del dispositivo, ya que aplica límites de memoria de forma correcta en procesos de destino específicos y verifica que las fugas o los picos de memoria aislados no provoquen una degradación del rendimiento en todo el sistema.

Mientras que los killers convencionales de memoria baja global actúan solo cuando todo el sistema está bajo presión, PMGD adopta un enfoque granular. El daemon logra esto supervisando los valores de memoria del grupo de control v2 para sus procesos objetivo. Cuando un proceso objetivo supera los límites de memoria configurados, pmgd controla los incumplimientos de límites registrando átomos de memoria de Statsd antes de finalizar el proceso.

Cómo funciona

El daemon usa inotify para escuchar eventos de presión de memoria (específicamente, actividad de memoria alta con memory.events). Cuando un proceso supervisado activa un evento de memoria, pmgd realiza las siguientes acciones:

  1. Verificación de memoria anónima: Evalúa la memoria anónima del proceso. Si supera el anon_limit_in_mb configurado, pmgd interrumpe el proceso de inmediato.
  2. Período de espera de recuperación: Si la memoria anónima está por debajo del límite especificado, pmgd espera un período de gracia de recuperación del sistema (reclaim_wait_time_secs).
  3. Evaluación de la memoria después de la recuperación: Si el valor de memory.current del proceso objetivo sigue siendo mayor o igual que memory.high después del período de gracia, o si la memoria anónima supera anon_limit_in_mb, pmgd finaliza el proceso de inmediato.

Esto se hace de forma continua hasta que se finaliza el proceso o hasta que la recuperación del proceso reduce su uso de memoria por debajo de los límites de memoria especificados.

Funciones de estado del sistema

  • Limitación de la tasa de reinicio: Para evitar bucles de inicio o fallas persistentes, pmgd hace un seguimiento de las finalizaciones de procesos en /data/misc/pmgd/history.json. El daemon restringe los procesos a una sola eliminación iniciada por pmgd por cada reinicio del dispositivo.

Configuración de SELinux

La capacidad de PMGD para supervisar procesos está restringida por la política de SELinux. Si configuras PMGD para supervisar un proceso cuyo dominio no está permitido por la política, como un proceso del sistema específico del proveedor, PMGD no podrá supervisarlo y es posible que veas denegaciones de SELinux en logcat.

Para permitir que PMGD supervise procesos en dominios adicionales, debes extender los permisos de PMGD actualizando la política de SELinux específica del dispositivo para PMGD.

El siguiente es un ejemplo de un archivo device/<vendor>/<device>/sepolicy/pmgd.te que agrega acceso a un dominio nuevo:

# Allow pmgd to access vendor_system_apps
r_dir_file(pmgd, vendor_system_apps)

Para obtener más información sobre cómo escribir políticas específicas del dispositivo, consulta Implementa SELinux.

Configuración definida por el proveedor

La configuración de PMGD se basa en el proveedor y se configura con un archivo JSON obligatorio /vendor/etc/pmgd/config.json. En esta lista, se indican los procesos que se deben hacer un seguimiento, su perfil de límite de memoria configurado (con perfiles de tareas de cgroup) y el límite de memoria anónima fijo en megabytes.

Campos de configuración del proveedor

La configuración JSON proporcionada es una lista de procesos y sus límites, definidos por los siguientes campos:

Campo Tipo Obligatorio Descripción Predeterminado
target_cmd String Nombre del comando del proceso objetivo que se supervisará, por ejemplo, system_server. N/A
uid Número entero No Es el ID de usuario (UID) del proceso. Si se omite, pmgd aplica la regla de forma global a cualquier proceso que coincida con target_cmd. N/A
reclaim_wait_time_secs Número entero No Es el período de gracia en segundos que se espera para que el sistema recupere memoria antes de volver a evaluar el límite de memoria. 5
mem_limit_profile String Nombre del perfil de tarea de cgroup que establece `memory.high`. Se usa para establecer el límite de memoria del proceso. N/A
anon_limit_in_mb Número entero Límite de memoria anónimo final en megabytes. Si la utilización de memoria anónima supera este valor, pmgd detiene el proceso de inmediato. N/A
additional_task_profiles Lista de strings No Es una lista de los perfiles de tareas adicionales a los que se aplica pmgd en el proceso cuando comienza la supervisión. Lista vacía

A continuación, se muestra un ejemplo de la configuración del perfil de tareas de cgroup en vendor/etc/task_profiles.json:

{
  "Attributes": [
    ...
    {
      "Name": "MemHigh",
      "Controller": "memory",
      "File": "memory.high"
    }
  ],
  "Profiles": [
    {
      "Name": "SystemServerMemoryHighLimit",
      "Actions": [
        {
          "Name": "SetAttribute",
          "Params":
          {
            "Name": "MemHigh",
            "Value": "1080M"
          }
        }
      ]
    }
  ]
}

A continuación, se muestra un ejemplo de la configuración de PMGD en vendor/etc/pmgd/config.json:

{
  "targets": [
    {
      "target_cmd": "system_server",
      "uid": 1000,
      "reclaim_wait_time_secs": 5,
      "mem_limit_profile": "SystemServerMemoryHighLimit",
      "anon_limit_in_mb": 300
    }
  ]
}