Процесс Android Low Memory Killer Daemon ( lmkd
) отслеживает состояние памяти работающей системы Android и реагирует на высокую нагрузку на память, завершая наименее важные процессы, чтобы поддерживать производительность системы на приемлемом уровне.
О давлении памяти
В системе Android, где параллельно запущено несколько процессов, могут возникать ситуации, когда системная память исчерпана, а процессы, требующие больше памяти, испытывают заметные задержки. Нехватка памяти — состояние, при котором системе не хватает памяти. Android освобождает память (чтобы снизить нагрузку) путём ограничения или завершения неважных процессов, запроса процессов на освобождение некритических кэшированных ресурсов и т. д.
Исторически Android отслеживал нагрузку на системную память с помощью встроенного в ядро драйвера LMK (Low Memory Killer), который представляет собой жёсткий механизм, зависящий от жёстко заданных значений. Начиная с версии ядра 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 (Pressure Stall Information) для получения уведомлений об уровнях нагрузки на память, а также использование функций контрольных групп памяти для ограничения ресурсов памяти, выделяемых каждому процессу, в зависимости от его важности.
Использование пользовательского пространства 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 | Устранить самую сложную из подходящих задач (лучшее решение) против любой подходящей задачи (быстрое решение). | false |
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 |