На платформе Android система пытается использовать как можно больше системной памяти (ОЗУ) и выполняет различные оптимизации памяти для освобождения места при необходимости. Эти оптимизации могут негативно повлиять на вашу игру, либо замедлив её, либо полностью завершив её работу. Подробнее об этих оптимизациях можно узнать в разделе « Распределение памяти между процессами» .
На этой странице описаны шаги, которые вы можете предпринять, чтобы избежать влияния нехватки памяти на вашу игру.
Ответить на вызов onTrimMemory()
Система использует onTrimMemory() для уведомления вашего приложения о событиях жизненного цикла, которые предоставляют хорошую возможность для вашего приложения добровольно сократить использование памяти и избежать завершения работы программой LMK (low-memory killer) для освобождения памяти для других приложений.
Если ваше приложение завершается в фоновом режиме, то при следующем запуске пользователем оно будет работать медленно и с перебоями . Приложения, которые уменьшают потребление памяти при переходе в фоновый режим, реже завершаются в фоновом режиме.
При обработке событий TRIM_MEMORY_UI_HIDDEN лучше всего освобождать большие объемы памяти, которые не требуются немедленно и могут быть восстановлены по запросу. Например, если ваше приложение имеет кэш растровых изображений, декодированных из локально хранящихся сжатых изображений, то часто бывает целесообразно очистить этот кэш в ответ на TRIM_MEMORY_UI_HIDDEN .
Котлин
class MainActivity : AppCompatActivity(), ComponentCallbacks2 { override fun onTrimMemory(level: Int) { if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) { // Release memory related to UI elements, such as bitmap caches. } if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) { // Release memory related to background processing, such as by // closing a database connection. } } }
Java
public class MainActivity extends AppCompatActivity implements ComponentCallbacks2 { public void onTrimMemory(int level) { switch (level) { if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) { // Release memory related to UI elements, such as bitmap caches. } if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) { // Release memory related to background processing, such as by // closing a database connection. } } } }
Не стоит слишком щепетильно относиться к объему памяти.
Планируйте использование памяти с запасом, чтобы избежать её нехватки. Следует учитывать следующие факторы:
- Объем физической оперативной памяти : Игры часто используют от ¼ до ½ объема физической оперативной памяти устройства.
- Максимальный размер zRAM : Больший размер zRAM означает, что у игры потенциально больше памяти для выделения. Этот объем может варьироваться в зависимости от устройства; чтобы узнать это значение, найдите
SwapTotalв файле/proc/meminfo. - Использование памяти операционной системой : Устройства, выделяющие больше оперативной памяти системным процессам, оставляют меньше памяти для вашей игры. Система завершает процесс вашей игры раньше, чем системные процессы.
- Использование памяти установленными приложениями : протестируйте свою игру на устройствах с большим количеством установленных приложений. Приложения социальных сетей и чатов работают постоянно и влияют на объем свободной памяти.
Если вы не можете придерживаться консервативного бюджета памяти, используйте более гибкий подход. Если система сталкивается с нехваткой памяти, уменьшите объем памяти, используемый игрой. Например, выделите текстуры с более низким разрешением или храните меньше шейдеров в ответ на вызов onTrimMemory() . Такой динамический подход к выделению памяти требует от разработчика больше работы, особенно на этапе проектирования игры.
Избегайте резких движений.
Трэшинг происходит, когда свободного места в памяти мало, но недостаточно, чтобы завершить работу игры. В этой ситуации kswapd освобождает страницы памяти, которые игре всё ещё нужны, поэтому он пытается загрузить эти страницы из памяти. Места недостаточно, поэтому страницы постоянно выгружаются в файл подкачки (непрерывная подкачка). Трассировка системы сообщает об этой ситуации как о потоке, в котором kswapd работает непрерывно.
Одним из признаков нестабильной работы игры является длительное время отклика кадров — возможно, секунда или больше. Для решения этой проблемы следует уменьшить объем памяти, потребляемой игрой.
Используйте доступные инструменты
В Android есть набор инструментов, помогающих понять, как система управляет памятью.
Меминформ
Этот инструмент собирает статистику использования памяти, чтобы показать, сколько памяти PSS было выделено и для каких категорий она использовалась.
Вывести статистику meminfo можно одним из следующих способов:
- Используйте команду
adb shell dumpsys meminfo package-name. - Используйте вызов
MemoryInfoиз API отладки Android.
Статистика PrivateDirty показывает объем оперативной памяти внутри процесса, который не может быть выгружен на диск и не используется другими процессами. Большая часть этого объема становится доступной системе после завершения этого процесса.
Точки трассировки памяти
Точки трассировки памяти отслеживают объем памяти RSS , используемой вашей игрой. Расчет использования памяти RSS намного быстрее, чем расчет использования памяти PSS. Благодаря более быстрому расчету, RSS показывает более детальные изменения размера памяти, что позволяет более точно измерять пиковое использование памяти. Поэтому легче заметить пики, которые могут привести к нехватке памяти в игре.
Идеально и длинные следы
Perfetto — это набор инструментов для сбора информации о производительности и памяти устройства и отображения её в веб-интерфейсе. Он поддерживает трассировки произвольной длины, позволяя отслеживать изменение RSS с течением времени. Вы также можете выполнять SQL-запросы к полученным данным для автономной обработки. Включите длинные трассировки в приложении «Системная трассировка» . Убедитесь, что для трассировки включена категория memory:Memory . Для пользовательской инструментации памяти в процессе разработки и тестирования вы также можете использовать API heapprofd (бета-версия).
heapprofd
heapprofd — это инструмент для отслеживания памяти, входящий в состав Perfetto. Этот инструмент помогает находить утечки памяти, показывая, где была выделена память с помощью malloc . heapprofd можно запустить с помощью скрипта Python, и, поскольку инструмент имеет низкие накладные расходы, он не влияет на производительность, в отличие от других инструментов, таких как Malloc Debug.
отчет об ошибке
bugreport — это инструмент для логирования, позволяющий выяснить, произошла ли ошибка в игре из-за нехватки памяти. Вывод инструмента гораздо подробнее, чем у logcat. Он полезен для отладки проблем с памятью, поскольку показывает, произошла ли ошибка в игре из-за нехватки памяти или же она была завершена процессом LMK.
Для получения дополнительной информации см. раздел «Сбор и чтение отчетов об ошибках» .