Android 17 и более поздние версии поддерживают ограничитель памяти, который представляет собой системную службу, отслеживающую и ограничивающую использование памяти процессами приложений с помощью Linux cgroup v2. Ограничитель памяти предотвращает чрезмерное потребление системной памяти отдельными приложениями, что снижает нагрузку на память в масштабах всей системы и предотвращает агрессивное завершение критически важных процессов из-за нехватки памяти (OOM).
Механизм
Ограничитель памяти интегрируется со службой управления активностью (AMS) для отслеживания событий жизненного цикла процесса и изменений состояния. Ограничитель памяти обеспечивает соблюдение ограничений памяти с помощью файловой системы cgroup v2 ядра Linux.
Для использования ограничителя памяти ядро устройства должно поддерживать cgroup v2 и контроллер memory . В частности, эта служба зависит от следующих атрибутов:
-
memory.high - Мягкое ограничение. При его превышении процесс замедляется, и ядро пытается освободить память.
-
memory.swap.max - Ограничивает объем пространства подкачки, которое может использовать процесс.
Влияние на приложения
Приложения, не превышающие лимит памяти, не затрагиваются ограничителем памяти.
Когда приложение превышает установленный лимит memory.high , ядро вытесняет файловую память приложения и выгружает анонимную память, чтобы приложение оставалось в пределах лимита. В результате вытеснения и выгрузки приложение может работать медленнее.
В крайнем случае, если приложение продолжит выделять анонимную память, и на устройстве закончится место подкачки, приложение может не выделить память и, как следствие, скорее всего, выйдет из строя.
Мониторинг процесса
По умолчанию ограничитель памяти отслеживает процессы приложений (UID >= 10000). Системные процессы, как правило, исключаются из этого списка, чтобы помочь проверить стабильность ядра системы.
Ограничитель памяти устанавливает лимиты памяти в зависимости от состояния процесса:
Видимые процессы — это процессы, воспринимаемые пользователем, такие как действия на переднем плане, службы переднего плана или другие состояния, которые можно заметить как замедление работы.
Невидимые процессы — это фоновые процессы, которые не взаимодействуют с пользователем и не видны ему.
В следующей таблице показано соответствие состояний конкретных процессов ограничениям памяти:
| Состояние процесса | Ограничение памяти |
|---|---|
PERSISTENT | Без ограничений |
PERSISTENT_UI | Без ограничений |
TOP | Видимый |
BOUND_TOP | Видимый |
FOREGROUND_SERVICE | Не видно |
BOUND_FOREGROUND_SERVICE | Не видно |
IMPORTANT_FOREGROUND | Видимый |
IMPORTANT_BACKGROUND | Не видно |
TRANSIENT_BACKGROUND | Не видно |
BACKUP | Не видно |
SERVICE | Не видно |
RECEIVER | Не видно |
TOP_SLEEPING | Видимый |
HEAVY_WEIGHT | Не видно |
HOME | Не видно |
LAST_ACTIVITY | Не видно |
CACHED_ACTIVITY | Кэшировано |
CACHED_ACTIVITY_CLIENT | Кэшировано |
CACHED_RECENT | Кэшировано |
CACHED_EMPTY | Кэшировано |
В кэшированном состоянии процессы замораживаются, а затем максимально освобождаются.
Когда процесс превышает установленный для него лимит memory.high , Memory Limiter обнаруживает это событие и может запустить действия по отладке, такие как создание профиля памяти или запись аномалии в statsd .
Конфигурация
Настройте ограничитель памяти с помощью XML-файла, расположенного в разделе vendor . Настройка позволяет задать абсолютные пределы памяти в зависимости от конкретных ограничений памяти устройства.
Путь к файлу:
/vendor/etc/memory-limiter-config.xmlКонфигурация по умолчанию: если файл конфигурации не найден, недоступен для чтения или недействителен, ограничитель памяти отключается.
формат XML
Конфигурационный файл соответствует схеме, определенной в memory-limiter-config.xsd . Файл позволяет задать несколько наборов ограничений; служба выбирает наиболее подходящий вариант на основе доступной оперативной памяти устройства. Все значения памяти заданы в мебибайтах (МиБ).
<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 - Положительное целое число, указывающее версию конфигурации. Должно быть равно 1.
-
minimumRequiredMemTotal - Минимальный объем доступной системной памяти, необходимый для корректной работы данного ограничения.
-
memVisible - Ограничение памяти (
memory.high) позволяло отображать процессы. -
memNotVisible - Ограничение памяти (
memory.high) позволяло запускать невидимые процессы. -
swapVisible - Ограничение на объем файла подкачки (
memory.swap.max) позволяло отображать процессы, находящиеся в видимом режиме. -
swapNotVisible - Ограничение на объем файла подкачки (
memory.swap.max) позволяло запускать невидимые процессы.
Изменить конфигурацию
Чтобы изменить общесистемные ограничения, выполните следующие действия:
- Измените файл
/vendor/etc/memory-limiter-config.xml. - Для вступления изменений в силу перезагрузите устройство или перезапустите
system_server.
Команды оболочки
Команда am memory-limiter позволяет вам и разработчикам взаимодействовать со службой во время выполнения для целей разработки и тестирования:
am memory-limiter <SUB-COMMAND>статус
Подкоманда status отображает рабочее состояние ограничителя памяти:
adb shell am memory-limiter statusПример выходных данных:
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
Ключевые поля в выходных данных включают:
-
monitoring - Указывает, отслеживает ли ограничитель активно процессы.
-
visibleMemиnotVisibleMem - Укажите рассчитанные абсолютные пределы объема памяти для каждого состояния.
-
events - Количество раз, когда процесс превысил свой лимит.
-
processes - Количество отслеживаемых процессов.
игнорировать
Подкоманда ignore временно исключает UID или все процессы из-под ограничений. Это действие полезно для тестирования производительности или когда конкретному приложению разрешается превышать установленные лимиты.
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
руководство
manual команда `handle` переопределяет рассчитанные ограничения для конкретного процесса (по идентификатору процесса, или PID) пользовательским абсолютным значением в мегабайтах (МБ):
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
Ручные настройки применяются только к жизненному циклу процесса. Если процесс перезапускается, он возвращается к ограничениям по умолчанию, основанным на его состоянии.