Инструмент Microprofile
UNIGINE поддерживает Microprofile, расширенный внешний встраиваемый профилировщик CPU / GPU с поддержкой покадровой проверки.
Профилировщик предоставляет следующие возможности:
- Операции профилирования, выполняемые движком на CPU и GPU
- Профилирование потоков движка
- Профилирование до 1000 кадров
- Вывод данных о производительности на локальный веб-сервер или в файл HTML
Запуск Microprofile#
Инструмент Microprofile доступен только для Development сборок движка: он не будет компилироваться для сборок Debug и Release. Вы можете использовать консольную команду microprofile_info, чтобы проверить, скомпилирован ли Microprofile.
Данные о производительности, полученные Microprofile могут выводиться на локальный веб-сервер или в файл HTML.
Включение и отключение Microprofile#
Microprofile отнимает много времени, поэтому мы рекомендуем вам включать его только при работе с ним и оставлять отключенным в противном случае.
Один из способов отключить Microprofile — снять флажок с соответствующей опции перед запуском UnigineEditor или приложения:
Другой способ — использовать консольную команду microprofile_enabled.
Сохранение данных о производительности в файл#
Microprofile позволяет сохранять данные о производительности в HTML-файл и затем анализировать их в автономном режиме.
Чтобы вывести данные о производительности в HTML-файл, выполните следующие действия:
- В консоли задайте количество кадров для профилирования с помощью консольной команды microprofile_dump_frames. Вы можете пропустить этот шаг: по умолчанию будет профилировано 500 кадров.
- Выполните консольную команду microprofile_dump_html.
Данные о производительности будут сохранены в указанном HTML-файле.
Использование дампов профилирования упрощает перехват "скачков" производительности: движок продолжает рендерить приложение в фоновом режиме, даже когда оно не в фокусе, поэтому кадр, на котором произошел скачок, может быть перезаписан в случае использования веб-сервера для визуализации данных производительности. Также его можно использовать для оценки результатов оптимизации: вы можете сделать дамп кадров до и после оптимизации и сравнить их.
Визуализация с использованием встроенного сервера#
Чтобы визуализировать данные о производительности с помощью локального веб-сервера, выполните следующие действия:
- В консоли установите количество кадров для профилирования с помощью консольной команды microprofile_webserver_frames . Вы можете пропустить этот шаг: по умолчанию будет профилировано 200 кадров.
-
В меню UnigineEditor выберите Tools -> Microprofile.
Данные о производительности будут отображаться в вашем веб-браузере.
- Вы можете отобразить только часть профилированных кадров: для этого в адресной строке веб-браузера добавьте /<number_of_frames> к текущему URL-адресу.
- Не забудьте обновить (F5) страницу в веб-браузере во время сбора данных профилирования, так как это не выполняется автоматически.
Например, если вы укажете localhost:1337/100, будут отображаться только первые 100 кадров.
Данные о производительности#
Microprofile визуализирует подробные данные о производительности для каждого кадра операций, выполняемых движком на CPU и GPU и в потоках движка. В главном меню Microprofile вы можете изменить режим визуализации: нажмите Mode и выберите нужный. По умолчанию установлен режим Detailed.
В режиме Detailed каждая операция (функция) и поток отображаются в виде отдельной цветной области. Регионы являются иерархическими: функция, вызванная другой функцией, отображается под последней. Размер области определяется временем выполнения соответствующей операции.
На рисунке ниже функция Engine::do_render() вызывает функции RenderRenderer::renderWorld() и так далее:
Чтобы просмотреть данные об определенной операции или потоке, наведите указатель мыши на соответствующую область. Чтобы увеличить / уменьшить отображаемые области, прокрутите колесико мыши.
Данные CPU#
В группе данных производительности Main отображается стек вызовов операций (например, update, rendering и т. д.), выполняемых движком на ЦП.
Данные GPU#
В группе данных о производительности GPU отображается стек вызовов операций, выполняемых движком на GPU. В дополнение к основным данным о производительности для каждой функции (например, рендеринга среды, рендеринга пост-материалов и т.д.) отображается количество вызовов DIP и визуализированных треугольников. Также может отображаться количество поверхностей, источников света, теней, отрендеренных этой функцией, количество используемых материалов и шейдеров; информация об узле или материале, для которого вызывается функция (идентификатор, имя и т.д.).
Когда указывается область, соответствующая определенной функции, отображается Microprofile, когда эта функция вызывается на CPU и сколько времени затрачивается на ее выполнение.
команды Vulkan или DirectX можно объединить в группы отладки графического процессора, которые создаются автоматически при определении области профилирования. Все графические ресурсы, загружаемые из внешних файлов, такие как текстуры, шейдеры, статические меши или меши со костной анимацией, а также внутренние ресурсы движка имеют свои собственные имена отладки для упрощения идентификации. Эта информация может быть полезна при использовании отладчиков Graphics API, таких как NVIDIA Nsight или RenderDoc.
Данные о потоках движка#
Данные о производительности потоков движка визуализируются в группах CPUThread, SoundThread, AsyncQueueThread, WorldSpawnMeshClutterThread, WorldSpawnGrassThread.
Использование Microprofile для логики Приложения#
Вы можете использовать Microprofile для проверки производительности логики вашего приложения.
- Откройте исходный код вашего приложения.
Include the UnigineProfiler.h file to get access to methods of the Profiler class.
#include <UnigineProfiler.h> using namespace Unigine;
- Найдите функцию или область видимости в коде, который вы хотите проверить.
-
В начале функции (или области видимости) вызовите Profiler::begin(). Укажите имя для захвата, которое будет отображаться в Microprofile.
Вы можете указать макрос __FUNCTION__, чтобы автоматически использовать класс и имя функции в качестве захвата. -
В конце функции (область действия) вызовите Profiler::end().
int AppWorldLogic::update() { // start profiling Profiler::begin("AppWorldLogic::update"); float time = Game::getTime(); float angle_0 = time * 1.0f; float angle_1 = time * 1.5f; float angle_2 = time * 2.0f; light_0->setWorldTransform(translate(Unigine::Math::Vec3(sinf(angle_0), cosf(angle_0), 1.0f) * 20.0f)); light_1->setWorldTransform(translate(Unigine::Math::Vec3(sinf(angle_1), cosf(angle_1), 1.0f) * 20.0f)); light_2->setWorldTransform(translate(Unigine::Math::Vec3(sinf(angle_2), cosf(angle_2), 1.0f) * 20.0f)); // stop profiling Profiler::end(); return 1; }
- Запустите проект.
- Откройте консоль и запустите команду microprofile_enabled 1.
- Перейдите в Microprofile и найдите регион с указанным названием.
Функции begin() и end() делают область профилирования доступной как для профилировщика, так и для Microprofile.
Если вы хотите использовать только Microprofile, создайте счетчик с помощью функций beginMicro() и endMicro().
int AppWorldLogic::update()
{
// start profiling
int id = Profiler::beginMicro("AppWorldLogic::update");
float time = Game::getTime();
float angle_0 = time * 1.0f;
float angle_1 = time * 1.5f;
float angle_2 = time * 2.0f;
light_0->setWorldTransform(translate(Unigine::Math::Vec3(sinf(angle_0), cosf(angle_0), 1.0f) * 20.0f));
light_1->setWorldTransform(translate(Unigine::Math::Vec3(sinf(angle_1), cosf(angle_1), 1.0f) * 20.0f));
light_2->setWorldTransform(translate(Unigine::Math::Vec3(sinf(angle_2), cosf(angle_2), 1.0f) * 20.0f));
// stop profiling
Profiler::endMicro(id);
return 1;
}
Создание вложенных счетчиков для профилирования#
Чтобы создать несколько вложенных счетчиков, вы должны использовать функции beginMicro() и endMicro(). beginMicro() возвращает идентификатор, который должен быть передан в endMicro(). Это позволяет создавать вложенные и пересекающиеся счетчики профилировщика.
В следующем примере используется комбинация begin()/end() и beginMicro()/endMicro(). Таким образом, профилирование функции AppWorldLogic::update() будет доступно как в профилировщике, так и в Microprofile.
int AppWorldLogic::update()
{
// start profiling
Profiler::begin("AppWorldLogic::update");
float time = Game::getTime();
float angle_0 = time * 1.0f;
float angle_1 = time * 1.5f;
float angle_2 = time * 2.0f;
// start profiling of the first light source (available in the Microprofile only)
int id_0 = Profiler::beginMicro("1st Light Update");
light_0->setWorldTransform(translate(Unigine::Math::Vec3(sinf(angle_0), cosf(angle_0), 1.0f) * 20.0f));
// stop profiling of the first light source
Profiler::endMicro(id_0);
// start profiling of the second light source (available in the Microprofile only)
int id_1 = Profiler::beginMicro("2nd Light Update");
light_1->setWorldTransform(translate(Unigine::Math::Vec3(sinf(angle_1), cosf(angle_1), 1.0f) * 20.0f));
// stop profiling of the second light source
Profiler::endMicro(id_1);
light_2->setWorldTransform(translate(Unigine::Math::Vec3(sinf(angle_2), cosf(angle_2), 1.0f) * 20.0f));
// stop profiling
Profiler::end();
return 1;
}
Логика профилирования с использованием макросов#
Существуют специальные макросы для обозначения фрагментов вашего кода, которые следует проверить. Их можно использовать вместо функций beginMicro() и endMicro():
-
UNIGINE_PROFILER_FUNCTION для проверки работоспособности функции.
Using Macro Using Functions void myFunction() { UNIGINE_PROFILER_FUNCTION; // your function code }
void myFunction() { int id = Profiler::beginMicro(__FUNCTION__); // your function code Profiler::endMicro(id); }
-
UNIGINE_PROFILER_SCOPED для проверки только определенной части кода.
Using Macro Using Functions void myFunction() { // your function code { UNIGINE_PROFILER_SCOPED("Scope name"); // your function code } }
void myFunction() { // your function code { int id = Profiler::beginMicro("Scope name"); // your function code Profiler::endMicro(id); } }