Timer

윈도우즈에서 자주 사용 되는 시간 체크 함수는 3가지가 있다.
3가지의 정밀도는 다음과 같다.

GetTickCount  <  timeGetTime   <  QueryPerformanceCounter

차례대로 알아 보자.

1. GetTickCount

윈도우가 시작 되어 흐른 시간을 1/1000( 밀리세컨 단위)로 DWORD 형을 리턴한다.
결과값이 32비트이기 때문에 49.71일까지 출력 할 수 있다.

GetTickCount의 해상도를 얻을려면 GetSystemTimeAdjustment를 이용하여 구할 수 있다.
윈도우즈 XP의 경우에는 15.625 밀리 세컨드 정도 나온다.
 

해상도 설정하기는 다음과 같다.

//GetTickCount의 해상도를 밀리세컨드 단위로 리턴한다.

float  GetTickResolutionMS()

{

    DWORD    dwt1,dwt2;

    BOOL     bDisabled;

 

    GetSystemTimeAdjustment(&dwt1, &dwt2, &bDisabled);

    float  res = (float)dwt2 * 100.0f * 1.0e-009f * 1.0e+003f;

    return  res;

}

사용법은 다음과 같다.

DWORD oldTime = GetTickCount();

시간을 잴 프로그래밍 루프들~~~

DWORD newTime = GetTickCount();
float fDelta = float( newTime - oldTime ) / 1000.0f;

 

2. timeGetTime

윈도우가 시작 되어 흐른 시간을 1/1000( 밀리세컨 단위)로 DWORD 형을 리턴한다.
결과값이 32비트이기 때문에 49.71일까지 출력 할 수 있다.

멀티 미디어 타이머로 GetTickCount보다 해상도가 좋다.
해상도를 1ms까지 설정 할 수 잇다.

해상도 설정은 다음과 같다.

timeBeginPeriod(1)

시간을 잴 프로그래밍 루프들~~~

timeEndPeriod(1);

timeBeginPeriod(1)은 1밀리센컨드로 해상도를 설정 하는것이다.
timeEndPeriod(1) 종료시에는 시작시 설정한 해상도로 설정한다.

시간 측정은 다음과 같다.

//헤더파일과 라이브러리 설정을 한다.
#include <windows.h>
#pragma comment(lib, "winmm.lib" )

DWORD oldTime = timeGetTime();

시간을 잴 프로그래밍 루프들~~~

DWORD newTime = timeGetTime();
float fDelta = float( newTime - oldTime ) * 0.001f;

 

3. QueryPerformanceCounter

고해상도 타이머로 가장 정밀도가 높다.

static  bool        s_bUsingQPF = false;

static  LONGLONG s_llQPFTicksPerSec = 0;

static  LONGLONG s_llLastElapsedTime = 0;

 

void  InitnStartCheckElapsedTime()

{

    LARGE_INTEGER qwTicksPerSec, qwTime;

    s_bUsingQPF = (bool) (QueryPerformanceFrequency( &qwTicksPerSec ) != 0);

 

    if( !s_bUsingQPF )

        return;

 

    s_llQPFTicksPerSec = qwTicksPerSec.QuadPart;

 

    QueryPerformanceCounter( &qwTime );

    s_llLastElapsedTime = qwTime.QuadPart;

}

 

float  GetElapsedTime()

{

    if( !s_bUsingQPF )

        return  -1.0;

 

    LARGE_INTEGER qwTime;

    QueryPerformanceCounter( &qwTime );

 

    float  fElapsedTime = (float)((double) ( qwTime.QuadPart - s_llLastElapsedTime ) / (double) s_llQPFTicksPerSec);

    s_llLastElapsedTime = qwTime.QuadPart;

 

    return  fElapsedTime;

}

시간 측정은 다음과 같다.

//초기화

InitnStartCheckElapsedTime();

 

float  oldTime = GetElapsedTime();

시간을 잴 프로그래밍 루프들~~~

float  newTime = GetElapsedTime();
float fDelta = newTime - oldTime;

멀티쓰레드에서 사용시에는 SetThreadAffinityMask를 사용한다.
HighTimer에서 사용예를 볼 수 있다.

4. HighTimer

고해상도 타이머 QueryPerformanceCounter를 클래스 화 시킨다.
SetThreadAffinityMask로 멀티쓰레드에 환경하에서도 사용 할 수 있게 한다.

시간 측정은 다음과 같다.

//HighTimer 첫번째
        HighTimer timer;
        timer.Start();

        시간을 잴 프로그래밍 루프들~~~

        timer.Stop();
        double  delta = timer.GetElapsedSec();

//HighTimer 두번째
        HighTimer timer;
        timer.Start();
        double sec1 = timer.GetDeltaSec();

        시간을 잴 프로그래밍 루프들~~~

        double  delta = timer.GetDeltaSec();

//HighTimer 세번째
        HighTimer timer;
        timer.Start();
        double start = timer.GetSec();

        시간을 잴 프로그래밍 루프들~~~

        double end = timer.GetSec();
        double delta = end - start;

아래의 테스트는 QueryPerformanceCounter와 GetTickCount, timeGetTime의 시간 해상도를 비교하기 위한 테스트이다..

Test_GetTickCount 함수는 GetTickCount와 QueryPerformanceCounter의 3초간 시간 오차를 비교 한것이다.

Test_timeGetTime 함수는 timeGetTime과 QueryPerformanceCounter의 3초간 시간 오차를 비교 한것이다.

void  main()

{

    {

        //QueryPerformanceCounter 함수를 이용한 시간 측정

        InitnStartCheckElapsedTime();

        float  fStart = GetElapsedTime();

        OutputDebugString( "test" );

        float  fEnd = GetElapsedTime();

        float  fDelta = fEnd - fStart;

        printf( "QueryPerformanceCounter 함수를 이용한 시간 측정 %f\n", fDelta );

    }

 

    {

        //HighTimer 클래스를 이용한 시간 측정

        HighTimer timer;

        timer.Start();

        OutputDebugString( "test" );

        timer.Stop();

        double  sec = timer.GetElapsedSec();  //

 

        double  sec1 = timer.GetDeltaSec();

        OutputDebugString( "test" );

        double  sec2 = timer.GetDeltaSec();

 

        double  start = timer.GetSec();

        OutputDebugString( "test" );

        double  end = timer.GetSec();

 

        printf( "HighTimer 클래스를 이용한 시간 측정 %f, %f, %f\n", sec, sec2, end - start );

    }

 

    //GetTickCount의 해상도 출력

    float  ms = GetTickResolutionMS();

    printf( "GetTickCount의 해상도는 %f Milli Second이다\", ms);

 

    //GetTickCount와 QueryPerformanceCounter( HighTimer 클래스 이용) 시간 비교

    Test_GetTickCount( 3.0f );

 

    //timeGetTime과 QueryPerformanceCounter( HighTimer 클래스 이용) 시간 비교

    Test_timeGetTime( 3.0f, true );   

 

    fflush(stdout);

    _getch();

}

윈도우즈 XP에서 테스트 한 출력 결과 화면이다.

ueryPerformanceCounter 함수를 이용한 시간 측정 0.000412
HighTimer 클래스를 이용한 시간 측정 0.000141, 0.000113, 0.000142
GetTickCount의 해상도는 15.625000 Milli Second이다
GetTickCount: 3.016000, HighTimer: 3.012481
 3.0 timeGetTime: 3.001953, HighTimer: 3.002012, 3.001976

소스 : timer.zip