Размер страницы – это гранулярность, с которой ОС управляет памятью. Большинство современных процессоров поддерживают страницы размером 4 КБ, поэтому ОС Android и приложения исторически создавались и оптимизировались для работы с такими страницами. Процессоры ARM поддерживают страницы памяти размером 16 КБ. Начиная с Android 15, в AOSP также можно создавать сборки Android со страницами памяти размером 16 КБ. Этот вариант использует дополнительную память, но повышает производительность системы. В Android 15 этот параметр не включен по умолчанию, но доступен в режиме разработчика или как параметр для разработчиков приложений и производителей устройств. Это позволяет подготовиться к переходу на режим 16 КБ в будущем.
В Android 15 и более поздних версиях поддерживается сборка Android с выравниванием ELF 16 КБ, которое работает с ядрами 4 КБ и 16 КБ, начиная с android14-6.1.
При использовании с ядром размером 16 КБ эта конфигурация требует дополнительной памяти, но повышает производительность системы.
Как настроить Android на использование страниц памяти размером 16 КБ
Страницы размером 16 КБ поддерживаются только на устройствах с целевой версией arm64 и ядрами размером 16 КБ.
Однако
на x86_64 для Cuttlefish можно смоделировать пространство пользователя размером 16 КБ.
Пространство ядра
Если для целевых объектов arm64 вы используете Kleaf для сборки ядра, --page_size=16k создает ядро в режиме 16 КБ.
Если вы напрямую используете конфигурацию ядра Linux, то можете выбрать страницы размером 16 КБ, задав значение CONFIG_ARM64_16K_PAGES вместо CONFIG_ARM64_4K_PAGES.
Пользовательское пространство
Чтобы включить поддержку страниц размером 16 КБ в пользовательском пространстве Android, задайте следующие параметры сборки:
PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := trueудаляетPAGE_SIZEdefine и заставляет компоненты определять размер страницы во время выполнения.PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384, чтобы файлы ELF платформы создавались с выравниванием по 16 КБ. Такой размер выбран для совместимости с будущими версиями. При выравнивании ELF по 16 КБ ядро может поддерживать страницы размером 4 КБ и 16 КБ.
Проверка флагов сборки
После выбора целевого объекта lunch убедитесь, что флаги сборки правильно настроены в среде:
$ source build/envsetup.sh
$ lunch target
$ get_build_var TARGET_MAX_PAGE_SIZE_SUPPORTED
16384
$ get_build_var TARGET_NO_BIONIC_PAGE_SIZE_MACRO
true
Если предыдущие две команды вернули значения 16384 и true соответственно, флаги сборки настроены правильно для работы с ядром размером 16 КБ. Однако даже если сборка прошла успешно, во время выполнения могут возникнуть проблемы из-за различий в среде размером 16 КБ.
Программирование системы с размером страницы 16 КБ
Большая часть кода на любом устройстве с ОС Android не имеет прямого отношения к размеру страницы. Однако для кода, работающего со страницами, поведение ядра при выделении памяти меняется, и вам нужно учитывать это, чтобы писать код, который не только совместим, но и максимально производителен и не требует много ресурсов.
Если вы вызовете mmap для области размером 1, 2 или 4 КБ в системе с размером страницы 4 КБ, система зарезервирует 4 КБ. Другими словами, при запросе памяти у ядра оно всегда должно округлять запрошенную память до ближайшего размера страницы. Например, если вы выделите область размером 5 КБ в области размером 4 КБ, ядро выделит 8 КБ.
В ядре размером 16 КБ эти дополнительные "хвосты" страниц больше. Например, при использовании ядра с размером страницы 16 КБ все эти выделения памяти (от 1 до 5 КБ) будут занимать 16 КБ. Если вы запросите 17 КБ, будет выделено 32 КБ.
Например, в системе с размером страницы 4 КБ можно выделить две анонимные области чтения-записи по 4 КБ. Однако при использовании ядра с размером страницы 16 КБ будет выделено две страницы, то есть 32 КБ. В ядре со страницами размером 16 КБ эти области можно объединить в одну страницу для чтения или записи, чтобы использовалось только 16 КБ. В этом случае по сравнению с ядром со страницами размером 4 КБ будет потеряно 8 КБ. Чтобы ещё больше сократить использование памяти, можно объединить больше страниц. На самом деле в максимально оптимизированной системе с размером страницы 16 КБ требуется меньше памяти, чем в системе с размером страницы 4 КБ, поскольку таблица страниц в первом случае в четыре раза меньше.
При использовании mmap обязательно округляйте запрашиваемый размер до ближайшего размера страницы. Это гарантирует, что весь объем памяти, выделяемый ядром, будет напрямую виден пользовательскому пространству в значениях времени выполнения, а не будет запрашиваться неявно и быть неявно или случайно доступным.
Создавайте общие библиотеки с выравниванием ELF по 16 КБ
Чтобы создать общие библиотеки, которые являются частью проекта для Android, достаточно настроек, описанных в разделе Включите размер страницы 16 КБ:
PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := truePRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384
Чтобы создать общие библиотеки, которые не входят в проект для Android, вам нужно передать этот флаг компоновщика:
-Wl,-z,max-page-size=16384
Проверьте двоичные файлы и предварительно созданные объекты на соответствие требованиям к выравниванию ELF для страниц размером 16 КБ
Чтобы проверить выравнивание и поведение во время выполнения, лучше всего протестировать и запустить скомпилированное ядро размером 16 КБ. Однако, чтобы выявлять некоторые проблемы раньше:
Начиная с Android 16, вы можете задать
PRODUCT_CHECK_PREBUILT_MAX_PAGE_SIZE := trueво время сборки. Чтобы временно игнорировать их, используйтеignore_max_page_size: trueвAndroid.bpиLOCAL_IGNORE_MAX_PAGE_SIZE := trueвAndroid.mk. Эти настройки проверяют все предварительно созданные сборки и позволяют обнаружить, когда одна из них обновлена, но не выровнена по 16 КБ.Вы можете запустить
atest elf_alignment_test, чтобы проверить выравнивание ELF-файлов на устройстве, на котором установлена ОС Android 15 или более поздняя версия.