gettimeofday()를 window에서 구현해서 사용하기

35 Comments

getimeofday()를 windows에서도 아래와 같이 구현해서 사용할 수 있고 또 그 것을 이용해서 코드의 수행 시간을 microsecond까지 측정할 수 있다.

최신 내용은 아래 wiki를 참조

 in my wiki: http://alones.byus.net/moniwiki/wiki.php/c_cpp_windows_tip_gettimeofday?action=show

  • initial version: 2007.06.03

OpenAsthra의 글들을 참고로 해서 작성하였다.

목차

1 gettimeofday in linux
2 gettimeofday in windows
2.1 Approach to gettimeofday in windows
2.2 code of gettimeofday in windows
2.3 usage of gettimeofday in windows
3 gettimeofday를 이용한 실행 시간 구하기
4 gettimeofday와 이 것을 이용한 전체 코드
5 References

1 gettimeofday in linux #

gettimeofday()는 아래 signature와 값이 system의 현재 시간을 가지고 온다.

#include <sys/time.h>
#include <unistd.h>

int gettimeofday(struct timeval *tv, struct timezone *tz);

//

첫 번째 인자는 다음과 같이 seconds와 microseconds를 가지고 있다. 즉, 현재 시간을 초와 마이크로초로 알 수 있는 유용한 api이다.

struct timeval
{
    long tv_sec;       // 초
    long tv_usec;      // 마이크로초
}

//

그리고 두 번째 인자는 쓰이지 않으면 NULL을 던져 주면 될 것이다.

2 gettimeofday in windows #

2.1 Approach to gettimeofday in windows #

Windows에는 gettimeofday()가 없다. 하지만 GetSystemTimeAsFileTime()을 이용해서 gettimeofday()를 만들 수 있다.

GetSystemTimeAsFileTime()은 다음과 같은 Signature를 가지고 현재 system의 date와 time을 Universal Time (UTC) format으로 반환해준다.

VOID GetSystemTimeAsFileTime(
  LPFILETIME lpSystemTimeAsFileTime  // file time
);

//

out parameter는 FILETIME struct로 다음과 같이 32bit 하위 bit와 32bit 상위 bit를 가지고 있다. 시간은 64bit 값으로 100 nanosecond단위이다.

typedef struct _FILETIME {
    DWORD dwLowDateTime;
    DWORD dwHighDateTime;
} FILETIME, *PFILETIME;

//

이 것을 FileTimeToSystemTime()을 이용해서 SYSTEMTIME으로 변경해서 사용하기도 할 것이다.

아무튼 windows에서 gettimeofday()를 만들기 위해서 우리는 다음과 같은 step을 따르면 될 것이다.

  1. GetSystemTimeAsFileTime()으로 system time을 구한다.
  2. 구한 시간인 FILETIME을 64bit로 합친다. (unsigned __int64)
  3. UNIX EPOCH time으로 변환한다. (웹을 검색해보면 쉽게 상수를 찾을 수 있다)
  4. 100nao를 micro로 변환하기 위해서 10을 나누어준다.
  5. second와 microsecond로 변환한다.

2.2 code of gettimeofday in windows #

위의 approach를 따른 코드는 다음과 같다.
#include < time.h >


// epoch time으로 변환할 상수
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
#else
#define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
#endif

// for timezone
struct timezone
{
  int  tz_minuteswest; /* minutes W of Greenwich */
  int  tz_dsttime;     /* type of dst correction */
};

// gettimeofday in windows
int gettimeofday(struct timeval *tv, struct timezone *tz)
{
  FILETIME ft;
  unsigned __int64 tmpres = 0;
  static int tzflag;

  if (NULL != tv)
  {
    // system time을 구하기
    GetSystemTimeAsFileTime(&ft);

    // unsigned 64 bit로 만들기
    tmpres |= ft.dwHighDateTime;
    tmpres <<= 32;
    tmpres |= ft.dwLowDateTime;

// 100nano를 1micro로 변환하기
tmpres /= 10;
// epoch time으로 변환하기 tmpres -= DELTA_EPOCH_IN_MICROSECS; // sec와 micorsec으로 맞추기 tv->tv_sec = (tmpres / 1000000UL); tv->tv_usec = (tmpres % 1000000UL); } // timezone 처리 if (NULL != tz) { if (!tzflag) { _tzset(); tzflag++; } tz->tz_minuteswest = _timezone / 60; tz->tz_dsttime = _daylight; } return 0; }

//

2.3 usage of gettimeofday in windows #

gettimeofday()는 아래와 같이 사용할 수 있을 것이다.

struct timeval now;
gettimeofday(&now, NULL);

printf("time: %ld sec %ld msec\n", now.tv_sec, now.tv_usec);

//

3 gettimeofday를 이용한 실행 시간 구하기 #

우리는 gettimeofday를 이용해서 코드의 수행 시간을 microsecond까지 측정할 수 있는 다음 함수를 만들 수 있을 것이다.

// 시간 측정
// event 1은 측정 시작
// event 2는 측정 완료 & print
void log_time(int event)
{
  static struct timeval tv_start;
  struct timeval tv_end;
  struct timeval *tv;

  tv = ((event==2)?&tv_end:&tv_start);

  gettimeofday(tv, NULL);

  if(event==2)
  {
          printf("Time: %ld  Seconds %ld  Microseconds\n",
           tv_end.tv_sec - tv_start.tv_sec,
           tv_end.tv_usec - tv_start.tv_usec);
  }
}

//

4 gettimeofday와 이 것을 이용한 전체 코드 #

#include < time.h >
#include <windows.h>
#include <iostream>
#include <stdio.h>

// epoch time으로 변환할 상수
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
  #define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
#else
  #define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
#endif

// for timezone
struct timezone
{
  int  tz_minuteswest; /* minutes W of Greenwich */
  int  tz_dsttime;     /* type of dst correction */
};

// gettimeofday in windows
int gettimeofday(struct timeval *tv, struct timezone *tz)
{
  FILETIME ft;
  unsigned __int64 tmpres = 0;
  static int tzflag;

  if (NULL != tv)
  {
    // system time을 구하기
    GetSystemTimeAsFileTime(&ft);

    // unsigned 64 bit로 만들기
    tmpres |= ft.dwHighDateTime;
    tmpres <<= 32;
    tmpres |= ft.dwLowDateTime;

    // epoch time으로 변환하기
    tmpres -= DELTA_EPOCH_IN_MICROSECS;

        // 100nano를 1micro로 변환하기
    tmpres /= 10;

        // sec와 micorsec으로 맞추기
        tv->tv_sec = (tmpres / 1000000UL);
        tv->tv_usec = (tmpres % 1000000UL);
  }

  // timezone 처리
  if (NULL != tz)
  {
    if (!tzflag)
    {
      _tzset();
      tzflag++;
    }
    tz->tz_minuteswest = _timezone / 60;
    tz->tz_dsttime = _daylight;
  }

  return 0;
}

// 시간 측정
// event 1은 측정 시작
// event 2는 측정 완료 & print
void log_time(int event)
{
  static struct timeval tv_start;
  struct timeval tv_end;
  struct timeval *tv;

  tv = ((event==2)?&tv_end:&tv_start);

  gettimeofday(tv, NULL);

  if(event==2)
  {
          printf("Time: %ld Seconds %ld Microseconds\n",
           tv_end.tv_sec - tv_start.tv_sec,
           tv_end.tv_usec - tv_start.tv_usec);
  }
}

void main()
{
        // method 1. directly use gettimeofday
        struct timeval now;
        struct timeval now2;

        gettimeofday(&now, NULL);

        Sleep(100);

        gettimeofday(&now2, NULL);

        long elpase_sec = now2.tv_sec - now.tv_sec;
        long elpase_usec = now2.tv_usec - now.tv_usec;

        printf("elapse: %ld sec %ld msec\n",
                               elpase_sec, elpase_usec);

        // method2. use log_time
        log_time(1);
        Sleep(1050);
        log_time(2);
}

//

5 References #