Хабрахабр

[Из песочницы] Профилируем Unity проект с Android Studio

Всем день добрый! Это статья о том, как профайлить Unity игры на Android с Android Studio. Я расскажу о том, как настроить Android Studio и получить максимальное кол-во данных. Вопросы анализа и выводов на основе полученного результата находятся вне рамок данной статьи.

Требования

Для полноценного профилирования приложения вам потребуется телефон с Android 8 или новее (API 27). По опыту, профилирование с Android-ами более старых версий несёт больше приключений, чем пользы. По этой причине я рекомендую обзавестись полной линейкой Nexus устройств, так как они имеют старое железо и последние обновления Android-а.

Настройка Unity проекта

Для получения результата, вам придётся настроить Unity проект определённым образом.

Настройки в Build Settings

image

  • В первую очередь, вы должны переключить Build System в “Gradle” и поставить галочку напротив “Export Project”. Таким образом мы получим готовый Android Studio проект, который мы и будем в дальнейшем профилировать. Профилирование готового APK тоже возможна, но более ограничена и требует больше подготовки
  • Режим “Development Build” желательно выключить, так как таким образом получаемые тайминги в профайлере будут максимально близки к реальным

Настройки в Player Settings

image

  • Установите Scripting Backend в IL2CPP. Если оставить Mono, то при нативном профилировании мы увидим много функций Mono, без информации как они соотносятся с C# кодом.
  • Опция ‘C++ Compiler Configuration’ для Android ни на что не влияет (в Unity 2018.3). Можете поставить её в ‘Release’, возможно в будущих версиях Unity Android toolchain эта настройка будет влиять на настройки компилятора.
  • Желательно ограничить ‘Target Architecture’ до ARMv7. Так вы сэкономите на времени компиляции и по опыту множество архитектур иногда вводит Android Studio в ступор.
  • Также стоит установить ряд дополнительных настроек:
    • Install Location — ‘Prefer external’
    • Internet Access — ‘Require’
    • Write Permission — ‘External (SDCard)’

    Android Studio и другие профайлеры используют simpleperf для сбора статистики, и ему потребуется доступ к карте памяти для записи временных файлов.

Подготовка Gradle проекта

После того, как вы установили все настройки, соберите Unity проект. Вы должны получить папку с Gradle проектом.
image

Потому вся отладочная информацию из него удалена, но к счастью её можно вернуть. Unity по умолчанию собирает проект из расчёта, что вы планируете собирать из него финальный APK. Для этого вам нужно подменить libil2cpp.so и libunity.so на версии с отладочной информацией.

libil2cpp.so

Это файл, который содержит весь C++ код, который IL2CPP сгенерировал из вашего C# кода. Unity генерирует всю необходимую для профилирования информацию, но для оптимизации размера APK, в процессе сборки вырезает её. Для того, чтобы вернуть её:

  • Пойдите в папку вашего проекта
  • Найдите в нём в подпапку Temp и перейдите в подпапку Temp/StagingArea/symbols/armeabi-v7a
  • Найдите в ней ‘libil2cpp.so.debug’. Это версия ‘libil2cpp.so’ с отладочной информацией
  • Теперь идите в Gradle проект и найдите в нем папку ‘\src\main\jniLibs\armeabi-v7a’
  • Замените ‘libil2cpp.so’ файлом ‘libil2cpp.so.debug’

libunity.so

Это файл, который содержит low-level часть Unity Player. Так как мы делаем Release сборку, то Unity положила вам в проект файл без отладочной информации. Вам нужно подменить libunity.so на файл с символами.

  • Пойдите в папку, где у вас установлена Unity
  • Перейдите в папку "\Data\PlaybackEngines\AndroidPlayer\Variations\il2cpp\Development\Libs\armeabi-v7a\"
  • Возьмите от туда файл libunity.so, и замените файл в вашем проекте, который лежит в папке ‘\src\main\jniLibs\armeabi-v7a’

Профилирование

Теперь вы можете начать профилировать в Android Studio, достаточно нажать кнопку запуска профайлера.

image

Android Studio запустит приложение и начнётся сессия профилирования

image

Для запуска процесса, вам нужно кликнуть на треке CPU, чтобы профайлер переключится на вид CPU. По умолчанию, Android Studio показывается графики, но не производит сэмплирование данных. При этом сверху окна появится дропдаун и кнопка ‘Record’.

image

3 — C/C++ Native), и нажмите кнопку ‘Record’.
Так как запись производится на диск устройства, по опыту лучше не записывать более 5-8 секунд, многие устройства будут фейлится и на меньшем кол-ве данных (список проверенных устройств смотрите в конце статьи). Выберите Sampled ‘Native’ (В Android Studio 3.

Сложно понять задумку авторов, но если вы не остановите запись полностью, то профайлер не всегда начинает анализ полученных данных и ваш отрезок с данным уедет в далёкие дали. Для получения результата нажмите ‘Stop’ и потом красный квадрат, чтобы прервать сессию.

image

Если всё настроено верно, вы получите capture со всем именами функций После этого остаётся только немного подождать, через 30-50 секунд профайлер выдаст вам результат.

image

Известные особенности

  • Наиболее стабильные результаты можно получить на root-ованных девайсах
  • Не используйте Samsung-и, на них есть множество защитных наворотов, которые мешают отладке
  • Во множестве мест ваш колстэк будет уходить в функции вида ‘kernel.kptr + адрес’. Это вызовы внутри Android Kernel, которые защищены из-за политики безопасности. На рутованном устройстве защиту можно отключить:
    • Запустите `adb shell`
    • Запустите `su` чтобы получить права root-пользователя
    • Выполните ‘sysctl -w kernel.kptr_restrict=0’ — это снимет защите с kernel-а
    • [!] После окончания отладки, выполните ‘sysctl -w kernel.kptr_restrict=1’. Некоторые устройства иначе при перезагрузке не смогут загрузить OS. Во многих случаях лечится только перепрошивкой чистого ядра.
  • Если Android Studio часто падает, можно попробовать увеличить heap Java VM:
    • 2Gb — для проектов среднего размера (‘-Xmx2g’)
    • 4Gb — для больших проектов (‘-Xmx4g’)
  • На нерутованных устройствах иногда улучшает ситуацию переключение ядра в ‘permissive mode’
    • Выполните команду ‘adb shell setenforce 0’

Unity специфика

  • Главный поток Unity называется UnityMain, но вы можете увидеть множество UnityMain при профилировании. Это пользовательские потоки, которые вы создаете внутри C# кода. По умолчанию они получают такое же имя. Главный поток Unity обычно легко отличить, так как он будет самый нагруженный.
  • Графический поток называется UnityGfxWorkerW
  • Потоки Unity Job системы называются Worker Thread
  • К сожалению некоторые wait-функции, которые применяет Unity (futex-ы), Android Studio показывает и считает не как wait-time, а как активность.
  • Когда вы будете смотреть call graph в Top Down view, вам придётся пройти через множество уровней Java-вызовом, к сожалению отфильтровать в Android Studio это никак нельзя.

image

Рекомендованные устройства

Мы для экспериментов использовали следующие устройства:

  • Samsung Galaxy S8
  • Google Pixel 2XL
  • Google Pixel
  • Sony Xperia XA1
  • Huawei Honor 7
  • Huawei Nexus 6P
  • Moto G5P
  • Asus Nexus 7 (2013)

Все устройства были зарутованы, для Huawei Nexus 6P мы собрали ядро и AOSP. По результату самыми беспроблемными и простыми для работы оказались Google и Sony. У Sony есть отличный сайт для разработчиков — Open Devices. Huawei больше не позволяет разблокировать устройства лёгким образом, Samsung вызывает постоянные сложности дополнительными уровнями защиты. Moto G5P часто приводил к падению процесса сбора данных профайлера (simpleperf).

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»