Оптимизация памяти имеет решающее значение для обеспечения стабильной и высокопроизводительной работы игр на Android. В этом руководстве представлен обзор того, почему важна эффективность использования памяти, как операционная система Android управляет и обеспечивает соблюдение ограничений на использование памяти процессами, а также новые пороговые значения, доступные в Google Play Console, которые помогут вам отслеживать и улучшать техническое качество вашей игры.
Важность оптимизации памяти
Оптимизация памяти вашей игры имеет важное значение для поддержания интереса игроков, расширения совместимости с устройствами и соответствия стандартам качества платформы:
- Предотвращение холодного запуска (улучшение пользовательского опыта и удержание игроков) : Когда игрок временно отключается от игры (например, чтобы ответить на уведомление или проверить сообщение), операционная система переводит игровой процесс в фоновый режим. Если объем памяти, используемой игрой в фоновом режиме, слишком велик, системный механизм Low Memory Killer (LMK) отдает приоритет завершению игрового процесса для освобождения оперативной памяти для задач переднего плана. При следующем возобновлении игры вместо плавного и мгновенного «теплого» возобновления, игре приходится проходить длительный холодный запуск — полную перезагрузку ресурсоемких графических ресурсов, звука и бинарных файлов игрового движка из памяти. Поддержание низкого уровня использования памяти в фоновом режиме предотвращает эти незаметные завершения фоновых процессов, сохраняя состояние пользователя и гарантируя, что игроки смогут немедленно возобновить свою сессию. Для получения более подробной информации о поведении системного механизма LMK см. руководство Android Vitals - Low memory killers .
- Стабильность экосистемы и устройства : Неэффективное использование памяти и утечки памяти ухудшают общее состояние системы. При нехватке памяти система испытывает сильное давление, что приводит к падению частоты кадров, подтормаживаниям пользовательского интерфейса и сбоям звука. Если давление на память слишком велико, механизм Low Memory Killer (LMK) агрессивно завершает фоновые процессы, заставляя другие приложения испытывать медленный холодный запуск и потерю пользовательского состояния при переключении между задачами.
- Завершение процессов на уровне платформы : начиная с Android 17 (уровень API 37), система более активно завершает процессы, использующие слишком много памяти. Если ваша игра потребляет слишком много памяти, ОС может внезапно завершить свой процесс без генерации стандартного трассировочного стека.
- Показатели видимости и меры контроля в магазине : Google Play запускает строгие меры контроля качества на основе показателей памяти в Android Vitals. Игры, которые постоянно превышают пороговые значения памяти в реальных условиях, рискуют столкнуться с такими мерами, как снижение органической видимости и снижение коэффициента конверсии.
- Совместимость с устройствами : Хотя флагманские устройства оснащены 12–16 ГБ оперативной памяти, значительная часть мировой игровой аудитории использует устройства с 4 или 6 ГБ ОЗУ. Правильное управление памятью гарантирует доступность и отзывчивость игры на всех уровнях аппаратного обеспечения без необходимости использования сложных отдельных пакетов ресурсов.
Понимание работы памяти в Android
Для разработки эффективных стратегий распределения памяти разработчикам необходимо понимать, как платформа Android управляет физической памятью и как она измеряет объем активной памяти, используемой игрой.
Основные концепции памяти Android
Основные понятия, касающиеся управления памятью на уровне платформы, см. в официальной документации «Обзор управления памятью» . Данный ресурс охватывает четыре архитектурные области:
- Обзор памяти : Android использует страничную организацию памяти и отображение в память (mmap) для управления оперативной памятью. Он не поддерживает традиционный файл подкачки на диске; вместо этого он полагается на сжатие страниц (с использованием zRAM) и освобождение памяти для освобождения физических страниц.
- Распределение памяти между процессами : Android распределяет оперативную память между всеми системами. Он выделяет определенные области памяти для выполнения виртуальных машин Dalvik или ART, позволяя при этом средам разработки (например, игровым движкам на C++) запрашивать память из системной области памяти.
- Управление памятью приложений : работая в многопроцессной модели, Android ожидает, что приложения будут динамически отслеживать состояние своего жизненного цикла и добровольно освобождать ненужные ресурсы (такие как некэшированная графика и растровые изображения) для поддержания работоспособности системы.
- Обзор процессов и потоков : Система классифицирует процессы в иерархическом порядке на основе их текущей видимости и важности, воспринимаемых пользователем, определяя, какие процессы остаются активными, а какие завершаются первыми в условиях нехватки памяти.
Показатель общего объема используемой памяти
Ограничитель памяти Android 17 на уровне платформы оценивает потребление памяти процессом, используя показатель общего объема используемой памяти (Total Memory Footprint), а не общий размер резидентной памяти (RSS) или размер виртуальной памяти.
Общий объем используемой памяти = Анонимный RSS (RssAnon) + Несжатый файл подкачки (VmSwap)
Чтобы предотвратить превышение играми установленных платформой ограничений, разработчики должны точно понимать, что означают эти метрики на системном уровне. Для получения дополнительной информации об этих метриках, физическом выделении оперативной памяти и обработке страниц, поддерживаемых файлами, см. раздел «Понимание метрик RSS и Swap» в руководстве по мониторингу использования памяти .
Ограничения памяти
Для поддержания стабильности системы и предотвращения чрезмерного потребления ресурсов приложениями платформа Android устанавливает ограничения на объем памяти для запущенных процессов.
Ограничитель памяти в Android 17 и выше
В Android 17 и более поздних версиях применяются строгие ограничения на использование памяти для каждого приложения с помощью Linux cgroup v2, чтобы предотвратить нестабильность системы в целом из-за отдельных приложений. Более подробную информацию о технической реализации см. в руководстве по ограничению памяти AOSP и в блоге «Приоритизация эффективности использования памяти: основные шаги для Android 17» .
- Механизм : Ограничитель памяти отслеживает все процессы приложения и динамически устанавливает ограничения в зависимости от состояния жизненного цикла процесса:
- Видимые процессы (в активном режиме) : Предполагается, что процессы приложения, в данный момент отображающие пользовательский интерфейс, будут использовать больший набор ресурсов и им будет предоставлен более щедрый лимит.
- Невидимые процессы (фоновые или сервисные) : процессы приложения, выполняющие активную работу без отображения пользовательского интерфейса, ограничены более жестким и ограниченным бюджетом.
- Атрибуты ядра : Сервис опирается на два основных атрибута:
-
memory.high: Мягкий лимит. При его превышении ядро ограничивает скорость процесса и пытается активно освободить память. Это освобождение может привести к снижению производительности игры. -
memory.swap.max: Устанавливает жесткое ограничение на объем подкачки или zRAM, который может использовать процесс.
-
- Поведение при завершении работы : Если процесс продолжает выделять анонимную память сверх значения
memory.highи исчерпывает свою емкость подкачки, выделение памяти завершается с ошибкой, и ОС молча завершает процесс. Это завершение регистрируется с помощьюApplicationExitInfoв разделе причины завершения работы Memory Limiter (доступно начиная с Android 17, 26Q4).
Отслеживание использования памяти
Для эффективной оптимизации памяти вашей игры необходимо сначала понять, как платформа Android измеряет её потребление. В Android 17 обновлена метрика принудительного использования памяти, теперь она отслеживает сумму анонимного RSS (RssAnon) и несжатого файла подкачки (VmSwap), исключая память, поддерживаемую файлами или выделенную для GPU. В этом руководстве подробно описано, как использовать системные инструменты, такие как Perfetto и meminfo , реализовать диагностические API, такие как ProfilingManager и onTrimMemory , и получить точные данные о выделении памяти в Unity и Unreal Engine. Узнайте, как точно профилировать вашу игру и избежать рывков производительности, связанных с традиционным опросом памяти во время выполнения.
Для получения более подробной информации см. раздел «Мониторинг использования памяти» .
стратегии сокращения памяти
Хотя игровые движки упрощают кроссплатформенную разработку, их стандартная обработка памяти может приводить к превышению лимитов памяти на уровне операционной системы. На этой странице подробно описаны практические шаги по оптимизации, специально разработанные для Unity и Unreal Engine. Вы поймете, почему использование onTrimMemory на основе Java может вызывать взаимоблокировки в Unity, и как вместо этого использовать нативные коллбэки жизненного цикла. Вы также узнаете о ключевых оптимизациях на уровне ресурсов, таких как использование сжатия текстур ASTC 8x8 и настройка выгрузки ресурсов, чтобы ваша игра работала плавно на всех уровнях оборудования.