★ 쓰레드 수행 시간
+ 시간 측정을 위해 대부분 GetTickCount64 함수를 이용
- 이 코드가 올바른 값을 획득하려면 코드 수행중 인터럽트가 수행되지 않았다는 가정 필요
- 선점형 운영체제에서는 쓰레드가 언제 CPU에 의해 수행될지 알수 없음
- 현재 코드를 수행 중 다른 작업 수행 가능
- 따라서, 쓰레드가 소비한 시간 부정확
- 실제 쓰레드가 부여받은 CPU 시간이 얼마나 되는지 알아내는 함수 필요
- GetThreadTimes / GetProcessTimes 함수 제공
+ TSC (Time Stamp Counter) 이용
- 비스타 이전에는 clock timer를 기반으로 10에서 15 밀리초 단위로 CPU 시간 계산
- 비스타 부터 머신이 기동된 후부터 얼마만큼의 CPU 사이클이 수행되었는지를 저장하고 있는 64bit의 TSC 이용
- 스레드가 스케줄러에 의해 정지되면 현재의 TSC 값과 스레드가 재시작되었던 시점에 획득된 TSC 값과의 차를 계산 후 쓰레드의 수행 시간에 더해줌
- QueryThreadCycleTime, QueryProcessCycleTime : 쓰레드와 프로세스에게 주어졌던 사이클 횟수
- ReadTimeStampCounter 매크로를 사용하여 현재 TSC 값 획득 가능
+ 보다 정밀한 시간 측정
- QueryPerformanceFrequency(LARGE_INTEGER* pliFrequency)
- QueryPerformanceCounter(LARGE_INTEGER* pliCount);
- 위 함수들은 윈도우 스케줄러가 해당 스레드를 선점하지 않을 경우에만 정확하게 시간 측정
- 아래는 코드
클래스 :
class CStopwatch
{
public:
CStopwatch() {QueryPerformanceFrequency(&m_liPerfFreq); Start();}
~CStopwatch(){};
void Start() { QueryPerformanceCounter (&m_liPerfStart);}
__int64 Now() const {
LARGE_INTEGER liPerfNow;
QueryPerformanceCounter(&liPerfNow);
return (((liPerfNow.QuadPart - m_liPerfStart.QuadPart) * 1000)
/ m_liPerfFreq.QuadPart);
}
__int64 NowInMicro() const {
LARGE_INTEGER liPerfNow;
QueryPerformanceCounter(&liPerfNow);
return (((liPerfNow.QuadPart - m_liPerfStart.QuadPart) * 100000)
/ m_liPerfFreq.QuadPart);
}
private:
LARGE_INTEGER m_liPerfFreq;
LARGE_INTEGER m_liPerfStart;
};
사용 :
CStopwatch stopwatch;
//시간 측정할 코드
__int64 qwElapsedTime = stopwatch.Now();
<출처 : 제프리 리처의 Windows via C/C++>