Profiler

posted in: CyberEnginePost | 0

have been adding more and more functionality to my engine and started to see that is my is my engine slowing down. To render or animate scene with 100 sprites in my engine dropped to 30 FPS , which is not very good as previously I was able to run it at 60 FPS. I have decided to add build-in profiler tool, which will be measure the execution time every single function in the game. Although I could use the build-in the Visual Studio profiling tools to find out what is hitting the performance, but I have decided that it would be nice to have my own tool which will be implemented in the engine and used whenever needed. I have implemented the ExecutionTimer class which measure the execution time of the function during its lifetime. This class start execution timer in the constructor and measure it until the object is destroyed.

 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//Measure the time of executing function. The lifetime of the function
struct ExecutionTimer
{
    std::chrono::time_point start;
    std::chrono::time_point end;
    std::chrono::duration<double, std::milli> duration;
    std::string m_FunctionName;
    std::string m_FileName;

    const float m_ErrorTime = 0.01f;
    const float m_WarningTime = 0.005f;

    ExecutionTimer(std::string fileName, std::string functionName)
    {
        m_FunctionName = functionName;
        m_FileName = fileName;
        start = std::chrono::high_resolution_clock::now();
    }

    ~ExecutionTimer()
    {
        end = std::chrono::high_resolution_clock::now();
        duration = end - start;

        ProfilerDataList_t::iterator result = std::find_if(ProfilerDataList.begin(), ProfilerDataList.end(),
            [&](const auto& element)
        {
            return (element._FunctionName == m_FunctionName && element._FileName == m_FileName);
        });

        if (result == ProfilerDataList.end())
        {
            //Not found
            ProfilerDataList.push_back(
                ProfilerData{
                    m_FileName,
                    m_FunctionName,
                    duration
                });
        }
        else
        {
            //Found element
            if (result->_ExecutionTime < duration)
            {
                result->_ExecutionTime = duration;
            }
        }
    }
};

To have simple access to the class I have decided to add a simple macro which could be put at the beginning of the function and measure its performance.


1
2
3
4
5
6
7
8
//to print only file name without full path
#define __FILENAME__ (strrchr(__FILE__,'\')+1)

#ifdef USE_PROFILER
#define SCOPE_MEMBER ExecutionTimer(__FILENAME__, __FUNCTION__)
#else
#define SCOPE_MEMBER (std::cout<<"")
#endif

All of the results are than saved in the vector files and outputted to the HTML report. Below is the report generated by the engine.

Slider

Leave a Reply

Your email address will not be published. Required fields are marked *