Процессы, завершенные из-за нехватки памяти

Демон LMK (low memory killer) в Android отслеживает состояние памяти работающей системы и реагирует на ее нехватку, завершая наименее важные процессы. Android Vitals отслеживает и регистрирует в Google Play Console случаи принудительного завершения работы приложения в активном режиме, чтобы вы могли выявлять проблемы с нехваткой памяти, которые влияют на пользователей.

Показатель LMK в Android Vitals

Android Vitals поможет вам отслеживать и улучшать частоту принудительного завершения процессов из-за нехватки памяти. В Android Vitals отслеживается только один показатель – доля сбоев LMK в активном режиме.

Этот показатель отражает процент активных пользователей за день, которые столкнулись по крайней мере с одним сбоем LMK в активном режиме. то есть при работе с приложением. Например, это могут быть сбои, произошедшие в тот момент, когда приложение показывает данные на экране или выполняется как активная служба. В результате процесс завершается немедленно и некорректно. Для конечного пользователя это выглядит как сбой приложения, часто в обход стандартных механизмов сохранения состояния жизненного цикла, что приводит к потере прогресса пользователя.

Android Vitals отслеживает такие завершения процессов, поскольку они служат надежным индикатором проблем с управлением памятью. Показатель LMK выше 1 % указывает на критическую необходимость немедленных действий. Однако низкий показатель LMK не всегда означает, что приложение использует память эффективно. Низкий показатель может означать, что демон LMK часто завершает фоновые процессы, что ухудшает производительность при теплом запуске и плавность работы в режиме многозадачности.

Этот показатель можно найти в разделе Стабильность в Android Vitals.

Рисунок 1. Перейдите к показателю Доля сбоев LMK в активном режиме в Android Vitals.

Как и в случае с другими основными показателями Android Vitals, например ошибками ANR и сбоями, вы можете фильтровать данные, сравнивать их с показателями других разработчиков и отслеживать изменения за длительный период (до трех лет). Для существующих приложений данные доступны с 28 января 2025 года.

Рисунок 2. Обзор доли сбоев LMK в Android Vitals.

Как работает демон LMKD

Платформа Android работает по принципу "свободная память – это память, которая не используется". Android всегда пытается использовать всю доступную память. Например, система сохраняет приложения в памяти после их закрытия, чтобы пользователь мог быстро вернуться к ним. Поэтому на устройствах Android часто остается очень мало свободной памяти (см. раздел Распределение памяти между процессами).

Чтобы решить, какой процесс завершить при нехватке памяти, демон LMK использует оценку нехватки памяти, которая называется oom_adj_score. Она позволяет расставить приоритеты для запущенных процессов. Процессы с высоким показателем завершаются первыми. Сначала закрываются фоновые приложения, а затем – системные процессы. В таблице ниже приведены категории оценки LMK от высокой к низкой. Объекты из категории с наибольшим количеством баллов (в первой строке) уничтожаются первыми:

Процессы Android, упорядоченные по убыванию оценки: фоновые приложения, предыдущее приложение, приложение Home, службы, заметные приложения, активное приложение, постоянные приложения, системные приложения и нативные приложения.
Рисунок 3. Процессы Android, отсортированные по оценке в порядке убывания.

Инструменты профилирования памяти

Следующие инструменты помогут вам найти и диагностировать проблемы с памятью:

  • Посмотрите, как ваше приложение распределяет память с течением времени. Вы увидите график, на котором в реальном времени отображается объем памяти, используемый приложением, количество выделенных объектов Java и время сборки мусора.
  • Инициируйте события сборки мусора и делайте снимки кучи Java во время работы приложения.
  • Записывайте данные о выделении памяти в приложении, проверяйте все выделенные объекты и просматривайте трассировку стека для каждого выделения.

Если игра работает на нативном движке, используйте HWAddress Sanitizer для отладки распределения памяти.

Профилировщик памяти Android Studio

Профилировщик памяти – это компонент Android Profiler, который помогает выявлять утечки и перемешивание памяти, приводящие к задержкам, зависаниям и даже сбоям в работе приложения. Профилировщик показывает график использования памяти в реальном времени и позволяет получить дамп кучи, принудительно запустить сборку мусора и отслеживать распределение памяти.

Профилировщик памяти Android Studio, показывающий глобальные ссылки JNI в куче.
Рисунок 4. Просмотр глобальных ссылок JNI в Профилировщике памяти Android Studio.

Инструменты Unity для профилирования памяти

Если вы используете Unity Engine, следуйте руководству по профилированию памяти в Unity. В Unity есть два инструмента для анализа использования памяти в приложении.

Первый – это модуль Профилировщика памяти, встроенный профилировщик, который предоставляет базовую информацию о том, где приложение использует память.

Модуль памяти показывает распределение памяти, например памяти текстур и памяти сетки.
Рисунок 5. Окно Unity Profiler с выбранным модулем Memory (Память).

Второй инструмент – пакет Профилировщик памяти, который можно добавить в проект Unity. Пакет добавляет дополнительное окно Memory Profiler в Unity Editor. Профилировщик памяти позволяет анализировать использование памяти в приложении ещё более подробно. Вы можете сохранять и сравнивать снимки, чтобы находить утечки памяти, или просматривать макет памяти, чтобы выявлять проблемы с фрагментацией памяти.

Окно Unity Профилировщика памяти с разбивкой снимка памяти.
Рисунок 6. Анализ снимка памяти в окне Профилировщика памяти.

Для рабочих процессов Unity, связанных с Android, ознакомьтесь со статьями Как проверить использование памяти с помощью инструментов Unity, Как оптимизировать использование памяти в Unity и Как выполнить отладку LMK для игр Unity.

Unreal Memory Insights

В приложениях, созданных с помощью Unreal Engine, можно использовать Unreal Memory Insights, чтобы просматривать подробную информацию о выделении и освобождении памяти, включая теги LLM и стеки вызовов, связанные с блоками памяти.

Система запросов Memory Insights может находить активные выделения памяти в любой момент времени, определять изменения в использовании памяти, находить утечки памяти и различать краткосрочные и долгосрочные выделения памяти.

Начиная с версии UE 5.4, Memory Insights поддерживает трассировку памяти со стеками вызовов для проектов для Android.

Трекер Memory Insights, на котором показаны график основной памяти, количество текущих распределений и количество событий выделения/освобождения памяти.
Рисунок 7. трекер Memory Insights в Unreal.

Информацию о рабочих процессах Unreal для Android можно найти в статьях Как проверить использование памяти в Unreal и Как оптимизировать использование памяти в Unreal.

Статистика по устройствам с малым объемом памяти

В Android есть обратные вызовы и API, которые позволяют сократить использование памяти и определить, почему предыдущие запуски игры были прерваны.

Обратные вызовы

Не регистрируйте устаревшие обратные вызовы trim. В Android нет API, которые бы обнаруживали нехватку нативной памяти до того, как система начнет ее освобождать. Кроме того, обратные вызовы для точной очистки оперативной памяти (TRIM_MEMORY_RUNNING_*) не помогают предотвратить завершение работы приложений при нехватке памяти. В результате в Android были объявлены устаревшими все уровни очистки, кроме TRIM_MEMORY_UI_HIDDEN и TRIM_MEMORY_BACKGROUND. Используйте оставшиеся обратные вызовы или эквиваленты жизненного цикла движка, такие как OnApplicationPause в Unity и ApplicationWillEnterBackgroundDelegate в Unreal, чтобы освободить ресурсы интерфейса и вспомогательные ресурсы, когда игра переходит в фоновый режим. Подробнее о том, как уменьшить объем памяти, используемой играми…

Завершение игры

Android пытается использовать всю доступную память для кеширования приложений и игр, чтобы они загружались быстрее (это повышает удобство использования). Однако когда память заканчивается, система закрывает самые ресурсоемкие приложения и игры, чтобы освободить память для нормальной работы устройства.

Ниже вы найдете информацию, статистику и рекомендации, которые помогут вам оптимизировать использование памяти в играх.

  • Используйте ApplicationExitInfo. Этот API возвращает причину, по которой предыдущий запуск игры был прерван системой Android. Используйте ApplicationExitInfo, чтобы проверить, не была ли предыдущая сессия завершена из-за нехватки памяти (REASON_LOW_MEMORY) или ограничений по ее использованию (REASON_MEMORY_LIMITER). Подробнее об ApplicationExitInfo для игр… Проверьте, не была ли игра закрыта из-за нехватки памяти. Если да, оптимизируйте ее, чтобы она использовала меньше памяти на этом устройстве.
  • Проверьте общий объем физической памяти. Чтобы игры не закрывались, когда они запущены на переднем плане, и соответствовали возможностям устройства, проверьте общий объем физической памяти на каждом устройстве и настройте использование памяти в игре. Если вы хотите, чтобы приложения не закрывались сразу после перехода в фоновый режим (чтобы игрок мог выполнять несколько задач одновременно), используйте обратные вызовы trim (в частности, TRIM_MEMORY_UI_HIDDEN), чтобы уменьшить использование памяти игрой.

Дополнительные ресурсы