Демон-демон 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 |