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

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

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

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

Исторически сложилось так, что Android отслеживал нехватку системной памяти с помощью встроенного в ядро ​​драйвера low memory killer (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-интерфейсу сжатия slab, который не был предназначен для тяжелых операций, таких как поиск целей и их уничтожение, что замедляло процесс vmscan .

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

Пользовательское пространство 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