gettimeofday()를 window에서 구현해서 사용하기
Jan 24
Programming/C/C plus plus FILETIME, FileTimeToSystemTime, getimeofday in windows, GetSystemTimeAsFileTime, gettimeofday, SYSTEMITM, UTC to EPOCH, 시간, 시간 측정, 현재 시간 구하기 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의 글들을 참고로 해서 작성하였다.
[edit]
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을 던져 주면 될 것이다.
[edit]
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을 따르면 될 것이다.
- GetSystemTimeAsFileTime()으로 system time을 구한다.
- 구한 시간인 FILETIME을 64bit로 합친다. (unsigned __int64)
- UNIX EPOCH time으로 변환한다. (웹을 검색해보면 쉽게 상수를 찾을 수 있다)
- 100nao를 micro로 변환하기 위해서 10을 나누어준다.
- second와 microsecond로 변환한다.
[edit]
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; }
//
[edit]
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);
//
[edit]
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); } }
//
[edit]
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); }
//
![[http]](http://alones.byus.net/moniwiki/imgs/http.png)
