Платформа Android исходит из того, что свободная память — это бесполезная трата памяти. Он всегда пытается использовать всю доступную память. Например, система сохраняет приложения в памяти после их закрытия, чтобы пользователь мог быстро вернуться к ним. По этой причине устройства Android часто работают с очень небольшим количеством свободной памяти. Управление памятью жизненно важно для правильного распределения памяти между важными системными процессами и многими пользовательскими приложениями.
На этой странице обсуждаются основы того, как Android распределяет память для системы и пользовательских приложений. Он также объясняет, как операционная система реагирует на ситуации с нехваткой памяти.
Типы памяти
Устройства Android содержат три разных типа памяти: RAM, zRAM и хранилище. Обратите внимание, что и процессор, и графический процессор имеют доступ к одной и той же оперативной памяти.
Рисунок 1. Типы памяти — RAM, zRAM и хранилище.
Оперативная память — самый быстрый тип памяти, но ее размер обычно ограничен. Устройства высокого класса обычно имеют самый большой объем оперативной памяти.
zRAM — это раздел оперативной памяти, используемый для пространства подкачки. Все сжимается при помещении в zRAM, а затем распаковывается при копировании из zRAM. Размер этой части ОЗУ увеличивается или уменьшается по мере того, как страницы перемещаются в zRAM или извлекаются из нее. Производители устройств могут установить максимальный размер.
Хранилище содержит все постоянные данные, такие как файловая система и включенный объектный код для всех приложений, библиотек и платформы. Память имеет гораздо большую емкость, чем два других типа памяти. В Android хранилище не используется для пространства подкачки, как в других реализациях Linux, поскольку частая запись может привести к износу этой памяти и сокращению срока службы носителя данных.
Страницы памяти
Оперативная память разбита на страницы . Обычно каждая страница занимает 4 КБ памяти.
Страницы считаются либо бесплатными , либо использованными . Свободные страницы — это неиспользуемая оперативная память. Используемые страницы — это оперативная память, которую система активно использует, и сгруппированы в следующие категории:
- Кэшированное: память, поддерживаемая файлом в хранилище (например, кодом или файлами, отображенными в памяти). Существует два типа кэшированной памяти:
- Частный: принадлежит одному процессу и не является общим.
- Очистить: немодифицированная копия файла в хранилище, может быть удалена с помощью
kswapd
для увеличения свободной памяти. - Грязный: измененная копия файла в хранилище; может быть перемещен в zRAM или сжат в него с помощью
kswapd
для увеличения свободной памяти.
- Очистить: немодифицированная копия файла в хранилище, может быть удалена с помощью
- Общий: используется несколькими процессами.
- Очистить: немодифицированная копия файла в хранилище, может быть удалена с помощью
kswapd
чтобы увеличить свободную память. - Грязный: измененная копия файла в хранилище; позволяет записывать изменения обратно в файл в хранилище для увеличения свободной памяти с помощью
kswapd
или явным использованиемmsync()
илиmunmap()
- Очистить: немодифицированная копия файла в хранилище, может быть удалена с помощью
- Частный: принадлежит одному процессу и не является общим.
- Анонимный: память, не поддерживаемая файлом в хранилище (например, выделенная с помощью
mmap()
с установленным флагомMAP_ANONYMOUS
).- Грязно: можно переместить/сжать в zRAM с помощью
kswapd
для увеличения свободной памяти.
- Грязно: можно переместить/сжать в zRAM с помощью
Пропорции свободных и используемых страниц со временем меняются, поскольку система активно управляет оперативной памятью. Концепции, представленные в этом разделе, являются ключевыми для управления ситуациями с нехваткой памяти. В следующем разделе этого документа они объясняются более подробно.
Низкое управление памятью
В Android есть два основных механизма для решения проблем с нехваткой памяти: демон подкачки ядра и убийца нехватки памяти.
демон подкачки ядра
Демон подкачки ядра ( kswapd
) является частью ядра Linux и преобразует используемую память в свободную. Демон становится активным, когда на устройстве заканчивается свободная память. Ядро Linux поддерживает низкие и высокие пороги свободной памяти. Когда свободная память падает ниже нижнего порога, kswapd
начинает освобождать память. Как только свободная память достигнет верхнего порога, kswapd
перестанет освобождать память.
kswapd
может восстановить чистые страницы, удалив их, поскольку они хранятся в хранилище и не были изменены. Если процесс пытается обратиться к чистой странице, которая была удалена, система копирует страницу из хранилища в ОЗУ. Эта операция известна как пейджинг по запросу .
Рисунок 2. Очищенная страница, сохраненная в хранилище, удалена
kswapd
может перемещать кэшированные частные и анонимные «грязные» страницы в zRAM, где они сжимаются. При этом освобождается доступная память в оперативной памяти (свободные страницы). Если процесс пытается коснуться грязной страницы в zRAM, страница распаковывается и перемещается обратно в ОЗУ. Если процесс, связанный со сжатой страницей, завершается, страница удаляется из zRAM.
Если объем свободной памяти падает ниже определенного порога, система начинает убивать процессы.
Рисунок 3. Грязная страница перемещена в zRAM и сжата.
Убийца с низкой памятью
Во многих случаях kswapd
не может освободить достаточно памяти для системы. В этом случае система использует onTrimMemory()
чтобы уведомить приложение о том, что памяти не хватает и что ей следует уменьшить ее выделение. Если этого недостаточно, ядро начинает убивать процессы, чтобы освободить память. Для этого он использует убийцу нехватки памяти (LMK).
Чтобы решить, какой процесс уничтожить, LMK использует показатель «нехватки памяти», называемый oom_adj_score
для определения приоритета запущенных процессов. Процессы с высоким рейтингом уничтожаются первыми. Фоновые приложения закрываются первыми, а системные процессы завершаются последними. В следующей таблице перечислены категории оценок LMK от высокой до низкой. Предметы в категории с наибольшим количеством баллов в первом ряду будут уничтожены в первую очередь:
Рисунок 4. Процессы Android: высокие оценки вверху и низкие оценки внизу.
Это описания различных категорий в таблице выше:
Фоновые приложения: приложения, которые запускались ранее и в настоящее время неактивны. LMK сначала уничтожит фоновые приложения, начиная с того, у которого самый высокий
oom_adj_score
.Предыдущее приложение: последнее использованное фоновое приложение. Предыдущее приложение имеет более высокий приоритет (более низкий балл), чем фоновые приложения, поскольку вероятность того, что пользователь переключится на него, выше, чем на одно из фоновых приложений.
Домашнее приложение: это приложение для запуска. Убив это, обои исчезнут.
Службы. Службы запускаются приложениями и могут включать синхронизацию или загрузку в облако.
Ощутимые приложения: приложения, не находящиеся на переднем плане, которые каким-то образом заметны пользователю, например, запуск процесса поиска с небольшим пользовательским интерфейсом или прослушивание музыки.
Приложение переднего плана: приложение, которое используется в данный момент. Закрытие приложения переднего плана выглядит как сбой приложения, который может указывать пользователю на то, что с устройством что-то не так.
Постоянные (службы): это основные службы устройства, такие как телефония и Wi-Fi.
Система: Системные процессы. Поскольку эти процессы завершаются, может показаться, что телефон перезагружается.
Собственный: процессы очень низкого уровня, используемые системой (например,
kswapd
).
Производители устройств могут изменить поведение ЛМК.
Вычисление объема памяти
Ядро отслеживает все страницы памяти в системе.
Рисунок 5. Страницы, используемые различными процессами
При определении объема памяти, используемого приложением, система должна учитывать общие страницы. Приложения, которые обращаются к одному и тому же сервису или библиотеке, будут совместно использовать страницы памяти. Например, сервисы Google Play и игровое приложение могут совместно использовать службу определения местоположения. Это затрудняет определение того, какой объем памяти принадлежит службе в целом по сравнению с каждым приложением.
Рисунок 6. Страницы, совместно используемые двумя приложениями (в центре)
Чтобы определить объем памяти, потребляемый приложением, можно использовать любую из следующих метрик:
- Размер резидентного набора (RSS): количество общих и закрытых страниц, используемых приложением.
- Размер пропорционального набора (PSS): количество частных страниц, используемых приложением, и равномерное распределение общих страниц (например, если три процесса совместно используют 3 МБ, каждый процесс получает 1 МБ в PSS).
- Размер уникального набора (USS): количество общих страниц, используемых приложением (общие страницы не включены).
PSS полезен для операционной системы, когда она хочет знать, сколько памяти используется всеми процессами, поскольку страницы не подсчитываются несколько раз. Расчет PSS занимает много времени, поскольку системе необходимо определить, какие страницы являются общими и каким количеством процессов. RSS не различает общие и необщие страницы (что ускоряет вычисления) и лучше подходит для отслеживания изменений в распределении памяти.
Дополнительные ресурсы
- Обзор управления памятью
- Процессы и жизненный цикл приложения
- Понимание использования памяти Android – презентация Google I/O
- Память Android и игры – презентация Google I/O
- Демон-убийца нехватки памяти Android
Пока рекомендаций нет.
Попытайтесь войти в свой аккаунт Google.