Integrating EasyProfilerÂ
Profiling enables developers to get vital measurement data and feedback in order to optimize the performance of their applications. EasyProfiler is a lightweight cross-platform profiler library for C++, which can be used to profile multithreaded graphical applications (https://github.com/yse/easy_profiler).
Getting ready
Our example is based on EasyProfiler version 2.1. The JSON snippet for Bootstrap to download it looks like this:
{ Â Â "name": "easy_profiler", Â Â "source": { Â Â Â Â "type": "archive", Â Â Â Â "url": "https://github.com/yse/easy_profiler/Â Â Â Â Â Â Â Â Â Â Â Â releases/download/v2.1.0/Â Â Â Â Â Â Â Â Â Â Â Â easy_profiler-v2.1.0-msvc15-win64.zip", Â Â Â Â "sha1":Â "d7b99c2b0e18e4c6f963724c0ff3a852a34b1b07" Â Â } }
There are two CMake options to set up in CMakeLists.txt
so that we can build EasyProfiler without the GUI and demo samples:
set(EASY_PROFILER_NO_GUI ON CACHE BOOL "") set(EASY_PROFILER_NO_SAMPLES ON CACHE BOOL "")
Now we are good to go and can use it in our application. The full source code for this recipe can be found in Chapter2/05_EasyProfiler
.
How to do it...
Let's build a small application that integrates EasyProfiler and outputs a profiling report. Perform the following steps:
- First, let's initialize EasyProfiler at the beginning of our
main()
function:#include <easy/profiler.h> ... int main() { Â Â EASY_MAIN_THREAD; Â Â EASY_PROFILER_ENABLE; Â Â ...
- Now we can manually mark up blocks of code to be reported by the profiler:
  EASY_BLOCK("Create resources");   const GLuint shaderVertex =    glCreateShader(GL_VERTEX_SHADER);   ...   const GLuint shaderFragment =    glCreateShader(GL_FRAGMENT_SHADER);   ...   GLuint perFrameDataBuffer;   glCreateBuffers(1, &perFrameDataBuffer);   ...   EASY_END_BLOCK;
Blocks can be automatically scoped. So, once we exit a C++ scope via
}
, the block will be automatically ended even if there is no explicit call toEASY_END_BLOCK
, as shown in the following snippet:Â Â { Â Â Â Â Â EASY_BLOCK("Set state"); Â Â Â Â Â glClearColor(1.0f, 1.0f, 1.0f, 1.0f); Â Â Â Â Â glEnable(GL_DEPTH_TEST); Â Â Â Â Â glEnable(GL_POLYGON_OFFSET_LINE); Â Â Â Â Â glPolygonOffset(-1.0f, -1.0f); Â Â }
- Let's create some nested blocks inside the main loop. We use
std::this_thread::sleep_for( std::chrono::milliseconds(2) )
to simulate some heavy computations inside blocks:Â Â while ( !glfwWindowShouldClose(window) )Â { Â Â Â Â Â EASY_BLOCK("MainLoop"); Â Â Â Â Â ... Â Â Â Â Â { Â Â Â Â Â Â Â Â EASY_BLOCK("Pass1"); Â Â Â Â Â Â Â Â std::this_thread::sleep_for( Â Â Â Â Â Â Â Â std::chrono::milliseconds(2) ); Â Â Â Â Â Â Â Â ... Â Â Â Â Â } Â Â Â Â Â { Â Â Â Â Â Â Â Â EASY_BLOCK("Pass2"); Â Â Â Â Â Â Â Â std::this_thread::sleep_for( Â Â Â Â Â Â Â Â std::chrono::milliseconds(2) ); Â Â Â Â Â Â Â Â ... Â Â Â Â Â } Â Â Â Â Â { Â Â Â Â Â Â Â Â EASY_BLOCK("glfwSwapBuffers()"); Â Â Â Â Â Â Â Â glfwSwapBuffers(window); Â Â Â Â Â } Â Â Â Â Â { Â Â Â Â Â Â Â Â EASY_BLOCK("glfwPollEvents()"); Â Â Â Â Â Â Â Â std::this_thread::sleep_for( Â Â Â Â Â Â Â Â std::chrono::milliseconds(2) ); Â Â Â Â Â Â Â Â glfwPollEvents(); Â Â Â Â Â } Â Â }
- At the end of the main loop, we save the profiling data to a file like this:
profiler::dumpBlocksToFile( "profiler_dump.prof" );
Now we can use the GUI tool to inspect the results.
How it works...
On Windows, we use the precompiled version of profiler_gui.exe
, which comes with EasyProfiler:
profiler_gui.exe profiler_dump.prof
The output should look similar to the following screenshot:
There's more...
Blocks can have different colors, for example, EASY_BLOCK("Block1", profiler::colors::Magenta)
. Besides that, there is an EASY_FUNCTION()
macro that will automatically create a block using the current function name as the block name. Custom ARGB colors can be used in the hexadecimal notation; for example, take a look at the following:
void bar() { Â Â EASY_FUNCTION(0xfff080aa); }