Демон-убийца нехватки памяти

Процесс устранения нехватки памяти Android ( lmkd ) отслеживает состояние памяти работающей системы Android и реагирует на высокую нехватку памяти, убивая наименее важные процессы, чтобы поддерживать производительность системы на приемлемом уровне.

О нехватке памяти

Система Android, выполняющая несколько процессов параллельно, может столкнуться с ситуациями, когда системная память исчерпана, а процессы, требующие большего объема памяти, испытывают заметные задержки. Нехватка памяти — состояние, при котором системе не хватает памяти, — требует, чтобы Android освободил память (чтобы облегчить нагрузку) путем регулирования или уничтожения неважных процессов, запроса процессов на освобождение некритических кэшированных ресурсов и т. д.

Исторически сложилось так, что Android отслеживал нехватку системной памяти с помощью встроенного в ядро ​​драйвера LMK — жесткого механизма, зависящего от жестко запрограммированных значений. Начиная с ядра 4.12, драйвер LMK удален из вышестоящего ядра, а пользовательское пространство lmkd выполняет задачи мониторинга памяти и уничтожения процессов.

Информация о стойле давления

Android 10 и более поздние версии поддерживают новый режим lmkd , который использует мониторы информации о давлении ядра (PSI) для обнаружения нехватки памяти. Набор патчей PSI в основном ядре (перенесенный в ядра 4.9 и 4.14) измеряет время, на которое задачи задерживаются из-за нехватки памяти. Поскольку эти задержки напрямую влияют на взаимодействие с пользователем, они представляют собой удобный показатель для определения серьезности нехватки памяти. Вышестоящее ядро ​​также включает в себя мониторы PSI, которые позволяют процессам привилегированного пользовательского пространства (таким как lmkd ) определять пороговые значения для этих задержек и подписываться на события ядра при нарушении порогового значения.

Мониторы PSI и сигналы vmpressure

Поскольку сигналы vmpressure (сгенерированные ядром для обнаружения нехватки памяти и используемые lmkd ) часто содержат множество ложных срабатываний, lmkd должен выполнить фильтрацию, чтобы определить, находится ли память под реальной нагрузкой. Это приводит к ненужным пробуждениям lmkd и использованию дополнительных вычислительных ресурсов. Использование мониторов PSI обеспечивает более точное определение нехватки памяти и минимизирует накладные расходы на фильтрацию.

Использование мониторов PSI

Чтобы использовать мониторы PSI вместо событий vmpressure , настройте свойство ro.lmk.use_psi . По умолчанию установлено значение true , что делает мониторинг PSI механизмом обнаружения нехватки памяти по умолчанию для lmkd . Поскольку мониторам PSI требуется поддержка ядра, ядро ​​должно включать исправления обратного порта PSI и быть скомпилировано с включенной поддержкой PSI ( CONFIG_PSI=y ).

Недостатки встроенного драйвера LMK

Android прекращает поддержку драйвера LMK из-за ряда проблем, в том числе:

  • Устройства с малым объемом оперативной памяти нужно было тщательно настраивать, и даже в этом случае они плохо работали при рабочих нагрузках с большим активным кэшем страниц, поддерживаемым файлами. Плохая игра привела к избиению и отсутствию убийств.
  • Драйвер ядра LMK полагался на ограничения свободной памяти без масштабирования в зависимости от нехватки памяти.
  • Из-за жесткости конструкции партнеры часто настраивали драйвер так, чтобы он работал на их устройствах.
  • Драйвер LMK подключался к API-интерфейсу сжатия плит, который не был предназначен для тяжелых операций, таких как поиск целей и их уничтожение, что замедляло процесс vmscan .

Пользовательское пространство lmkd

Пользовательское пространство lmkd реализует ту же функциональность, что и встроенный в ядро ​​драйвер, но использует существующие механизмы ядра для обнаружения и оценки нехватки памяти. Такие механизмы включают использование генерируемых ядром событий vmpressure или мониторов информации о остановке давления (PSI) для получения уведомлений об уровнях нехватки памяти, а также использование функций контрольной группы памяти для ограничения ресурсов памяти, выделяемых каждому процессу, в зависимости от важности процесса.

Использование пользовательского пространства lmkd в Android 10

В Android 9 и более поздних версиях пользовательское пространство lmkd активируется, если встроенный в ядро ​​драйвер LMK не обнаружен. Поскольку в пользовательском пространстве lmkd требуется поддержка ядром контрольных групп памяти, ядро ​​необходимо скомпилировать со следующими параметрами конфигурации:

CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y

Стратегии убийства

Пользовательское пространство lmkd поддерживает стратегии уничтожения, основанные на событиях vmpressure или мониторах PSI, их серьезности и других подсказках, таких как использование подкачки. Стратегии уничтожения различаются для устройств с низким объемом памяти и высокопроизводительных устройств:

  • На устройствах с малым объемом памяти система должна допускать более высокий уровень нехватки памяти в обычном режиме работы.
  • На высокопроизводительных устройствах нехватку памяти следует рассматривать как ненормальную ситуацию и устранять ее до того, как она повлияет на общую производительность.

Вы можете настроить стратегию уничтожения, используя свойство ro.config.low_ram . Подробности см. в разделе Конфигурация с низким объемом оперативной памяти .

Пользовательское пространство lmkd также поддерживает устаревший режим, в котором он принимает решения об уничтожении, используя те же стратегии, что и встроенный в ядро ​​драйвер LMK (то есть пороговые значения свободной памяти и файлового кэша). Чтобы включить устаревший режим, установите для свойства ro.lmk.use_minfree_levels значение true .

Настройка lmkd

Настройте lmkd для конкретного устройства, используя следующие свойства.

Свойство Использовать По умолчанию
ro.config.low_ram Укажите, является ли устройство устройством с низким объемом оперативной памяти или высокопроизводительным. false
ro.lmk.use_psi Используйте мониторы PSI (вместо событий vmpressure ). true
ro.lmk.use_minfree_levels Используйте пороговые значения свободной памяти и файлового кэша для принятия решений об уничтожении процесса (то есть соблюдайте функциональность встроенного драйвера LMK). false
ro.lmk.low Минимальный показатель oom_adj для процессов, которые могут быть завершены при низком уровне vmpressure . 1001
(неполноценный)
ro.lmk.medium Минимальный показатель oom_adj для процессов, которые могут быть завершены на среднем уровне vmpressure . 800
(кэшированные или несущественные службы)
ro.lmk.critical Минимальный показатель oom_adj для процессов, которые могут быть завершены при критическом уровне vmpressure . 0
(любой процесс)
ro.lmk.critical_upgrade Включите обновление до критического уровня. false
ro.lmk.upgrade_pressure Максимальное mem_pressure , при котором уровень повышается, поскольку система слишком много подкачивает. 100
(неполноценный)
ro.lmk.downgrade_pressure Минимальное mem_pressure , при котором событие vmpressure игнорируется, поскольку все еще доступно достаточно свободной памяти. 100
(неполноценный)
ro.lmk.kill_heaviest_task Убейте самую тяжелую подходящую задачу (лучшее решение) по сравнению с любой подходящей задачей (быстрое решение). true
ro.lmk.kill_timeout_ms Продолжительность в миллисекундах после убийства, когда дополнительные убийства выполняться не будут. 0
(неполноценный)
ro.lmk.debug Включите журналы отладки lmkd . false

Пример конфигурации устройства:

PRODUCT_PROPERTY_OVERRIDES += \
    ro.lmk.low=1001 \
    ro.lmk.medium=800 \
    ro.lmk.critical=0 \
    ro.lmk.critical_upgrade=false \
    ro.lmk.upgrade_pressure=100 \
    ro.lmk.downgrade_pressure=100 \
    ro.lmk.kill_heaviest_task=true

Пользовательское пространство lmkd в Android 11

Android 11 улучшает lmkd , вводя новую стратегию убийства. Стратегия уничтожения использует механизм PSI для обнаружения нехватки памяти, представленный в Android 10. lmkd в Android 11 учитывает уровни использования ресурсов памяти и их перегрузку, чтобы предотвратить нехватку памяти и снижение производительности. Эта стратегия уничтожения заменяет предыдущие стратегии и может использоваться как на высокопроизводительных устройствах, так и на устройствах с низким объемом оперативной памяти (Android Go).

Требования ядра

Для устройств Android 11 lmkd требует наличия следующих функций ядра:

  • Включите патчи PSI и включите PSI (бэкпорты доступны в общих ядрах Android 4.9, 4.14 и 4.19).
  • Включите исправления поддержки PIDFD (обратные порты доступны в общих ядрах Android 4.9, 4.14 и 4.19).
  • Для устройств с низким объемом оперативной памяти включите контрольные группы памяти.

Ядро должно быть скомпилировано со следующими настройками конфигурации:

CONFIG_PSI=y

Настройка lmkd в Android 11

Стратегия уничтожения памяти в Android 11 поддерживает ручки настройки и настройки по умолчанию, перечисленные ниже. Эти функции работают как на высокопроизводительных устройствах, так и на устройствах с низким объемом оперативной памяти.

Свойство Использовать По умолчанию
Высокая производительность Низкий объем оперативной памяти
ro.lmk.psi_partial_stall_ms Частичный порог задержки PSI в миллисекундах для запуска уведомления о нехватке памяти. Если устройство получает уведомления о нехватке памяти слишком поздно, уменьшите это значение, чтобы активировать более ранние уведомления. Если уведомления о нехватке памяти срабатывают без необходимости, увеличьте это значение, чтобы сделать устройство менее чувствительным к шуму. 70 200
ro.lmk.psi_complete_stall_ms Полный порог остановки PSI в миллисекундах для запуска уведомлений о критической памяти. Если устройство получает уведомления о критическом нехватке памяти слишком поздно, уменьшите это значение, чтобы активировать более ранние уведомления. Если уведомления о критическом нехватке памяти срабатывают без необходимости, увеличьте это значение, чтобы сделать устройство менее чувствительным к шуму. 700
ro.lmk.thrashing_limit Максимальное количество сбоев рабочего набора в процентах от общего размера файлового кэша страниц. Сбои рабочего набора выше этого значения означают, что система перегружает свой кэш страниц. Если нехватка памяти влияет на производительность устройства, уменьшите значение, чтобы ограничить тряску. Если производительность устройства без необходимости снижается из-за сбоев, увеличьте значение, чтобы обеспечить более высокий уровень сбоев. 100 30
ro.lmk.thrashing_limit_decay Снижение порога сбоя выражается в процентах от исходного порога, используемого для понижения порога, когда система не восстанавливается, даже после уничтожения. Если продолжительное избиение приводит к ненужным убийствам, уменьшите значение. Если реакция на постоянные избиения после убийства слишком медленная, увеличьте значение. 10 50
ro.lmk.swap_util_max Максимальный объем подкачиваемой памяти в процентах от общего объема подкачиваемой памяти. Когда объем подкачиваемой памяти превышает этот предел, это означает, что система заменила большую часть своей подкачиваемой памяти и все еще находится под нагрузкой. Это может произойти, когда неперемещаемые выделения создают нагрузку на память, которую нельзя уменьшить путем замены, поскольку большая часть подкачиваемой памяти уже выгружена. Значение по умолчанию — 100, что фактически отключает эту проверку. Если на производительность устройства влияет нехватка памяти при высоком использовании подкачки и уровень свободной подкачки не падает до ro.lmk.swap_free_low_percentage , уменьшите значение, чтобы ограничить использование подкачки. 100 100

Следующие старые ручки настройки также работают с новой стратегией убийства.

Свойство Использовать По умолчанию
Высокая производительность Низкий объем оперативной памяти
ro.lmk.swap_free_low_percentage Уровень свободного подкачки в процентах от общего пространства подкачки. `lmkd` использует это значение в качестве порога, когда следует считать, что в системе не хватает места подкачки. Если lmkd завершает работу, когда в подкачке слишком много места, уменьшите процент. Если убийства `lmkd` происходят слишком поздно и позволяют совершать убийства OOM, увеличьте процент. 20 10
ro.lmk.debug Это активирует журналы отладки lmkd. Включите отладку во время настройки. false