14 8月 2013

[Win32] 在C/C++中偵測精準的程式時間(Performance Time)

在Windows底下,要偵測精準的Perfromance Time,可以透過QueryPerformanceFrequency() & QueryPerformanceCounter() 來取得。

由於取得的時間存在LARGE_INTEGER的structure,要取出來計算所花費的時間需要多點程式碼才行。這邊寫了一個簡單的Wrapper Class,讓這個AutoQueryPerformance的instance life-time結束後,自行dump出所花費的時間。

AutoQueryPerformance

#include "windows.h"

// Auto dump the life-time of AutoQueryPerformance
// Ex:
// {
//     AutoQueryPerformance autoQuery("Test", true);
//     ...
// } // it will dump message when @autoQuery destroy
class AutoQueryPerformance
{
public:
    AutoQueryPerformance(const char* info, INT loop_count=1, BOOL autoDump=TRUE)
        : m_count_time(0), m_loop_count(loop_count), m_auto(autoDump)
    {
        m_info = info;
        ::ZeroMemory(&m_cpu_freq, sizeof(LARGE_INTEGER));
        ::QueryPerformanceFrequency(&m_cpu_freq);

        if( autoDump )
            begin();
    }
    ~AutoQueryPerformance()
    {
        pause();
        if( autoDump )
            printf("[AutoQueryPerformance][%s] spend time=%.4f", m_info.c_str(), getTime());
    }
    inline void begin()
    {
        ::ZeroMemory(&m_start_clock, sizeof(LARGE_INTEGER));;
        ::QueryPerformanceCounter(&m_start_clock);
    }
    inline void pause()
    {
        ::ZeroMemory(&m_cur_clock, sizeof(LARGE_INTEGER));
        ::QueryPerformanceCounter(&m_cur_clock);
        m_count_time += m_cur_clock.QuadPart-m_start_clock.QuadPart;
    }
    inline void stop()
    {
        pause();
        m_count_time = 0;
    }
    inline float getTime()
    {
        return (m_count_time/(float)m_cpu_freq.QuadPart) / m_loop_count;
    }
private:
    LARGE_INTEGER m_cpu_freq;
    LARGE_INTEGER m_start_clock;
    LARGE_INTEGER m_cur_clock;
    LONGLONG      m_count_time;
    INT           m_loop_count;//for for-loop to calculate correct average time
    std::string   m_info;
    BOOL          m_auto;
};
#define AUTO_QUERY_PERFORMANCE(x) AutoQueryPerformance __at_qp = AutoQueryPerformance(x);


使用範例

void TestingTotalTime(int loop_count)
{
    AutoQueryPerformance ap("TestingTotalTime");
    int sum = 0;
    for(int i=0 ; i<loop_count; i++)
       sum += i;
}

void TestingSingleTime(int loop_count)
{
    AutoQueryPerformance ap("TestingSingleTime", loop_count);
    for(int i=0 ; i<loop_count; i++)
       //HeavyFunction call here;
}

Reference

沒有留言: