将clock_gettime移植到窗口

我有以下代码在qnx momemntics上运行。

#define BILLION 1000000000L; struct timespec start_time; struct timespec stop_time; void start MyTestFunc() { //Initialize the Test Start time clock_gettime(CLOCK_REALTIME,&start_time) // ... additonal code. cout << "The exectuion time of func "<< calculateExecutionTime(); } double calculateExecutionTime () { clock_gettime(CLOCK_REALTIME,&stop_time); double dSeconds = (stop_time.tv_sec - start_time.tv_sec); double dNanoSeconds = (double)( stop_time.tv_nsec - start_time.tv_nsec ) / BILLION; return dSeconds + dNanoSeconds; } 

现在我想将上面的代码移植到Windows。 任何人都可以提供示例代码。

谢谢!

您可以按如下所示实现windows的clock_gettime()替换:

 LARGE_INTEGER getFILETIMEoffset() { SYSTEMTIME s; FILETIME f; LARGE_INTEGER t; s.wYear = 1970; s.wMonth = 1; s.wDay = 1; s.wHour = 0; s.wMinute = 0; s.wSecond = 0; s.wMilliseconds = 0; SystemTimeToFileTime(&s, &f); t.QuadPart = f.dwHighDateTime; t.QuadPart <<= 32; t.QuadPart |= f.dwLowDateTime; return (t); } int clock_gettime(int X, struct timeval *tv) { LARGE_INTEGER t; FILETIME f; double microseconds; static LARGE_INTEGER offset; static double frequencyToMicroseconds; static int initialized = 0; static BOOL usePerformanceCounter = 0; if (!initialized) { LARGE_INTEGER performanceFrequency; initialized = 1; usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency); if (usePerformanceCounter) { QueryPerformanceCounter(&offset); frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.; } else { offset = getFILETIMEoffset(); frequencyToMicroseconds = 10.; } } if (usePerformanceCounter) QueryPerformanceCounter(&t); else { GetSystemTimeAsFileTime(&f); t.QuadPart = f.dwHighDateTime; t.QuadPart <<= 32; t.QuadPart |= f.dwLowDateTime; } t.QuadPart -= offset.QuadPart; microseconds = (double)t.QuadPart / frequencyToMicroseconds; t.QuadPart = microseconds; tv->tv_sec = t.QuadPart / 1000000; tv->tv_usec = t.QuadPart % 1000000; return (0); } 

避免PerformanceCounter混乱,简单的代码:

 struct timespec { long tv_sec; long tv_nsec; }; //header part int clock_gettime(int, struct timespec *spec) //C-file part { __int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime); wintime -=116444736000000000i64; //1jan1601 to 1jan1970 spec->tv_sec =wintime / 10000000i64; //seconds spec->tv_nsec =wintime % 10000000i64 *100; //nano-seconds return 0; } 

高精度并不重要时,快速,可靠和正确的移植解决方案。

基于QPC的全解决方案是:

 struct timespec { long tv_sec; long tv_nsec; }; //header part #define exp7 10000000i64 //1E+7 //C-file part #define exp9 1000000000i64 //1E+9 #define w2ux 116444736000000000i64 //1.jan1601 to 1.jan1970 void unix_time(struct timespec *spec) { __int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime); wintime -=w2ux; spec->tv_sec =wintime / exp7; spec->tv_nsec =wintime % exp7 *100; } int clock_gettime(int, timespec *spec) { static struct timespec startspec; static double ticks2nano; static __int64 startticks, tps =0; __int64 tmp, curticks; QueryPerformanceFrequency((LARGE_INTEGER*)&tmp); //some strange system can if (tps !=tmp) { tps =tmp; //init ~~ONCE //possibly change freq ? QueryPerformanceCounter((LARGE_INTEGER*)&startticks); unix_time(&startspec); ticks2nano =(double)exp9 / tps; } QueryPerformanceCounter((LARGE_INTEGER*)&curticks); curticks -=startticks; spec->tv_sec =startspec.tv_sec + (curticks / tps); spec->tv_nsec =startspec.tv_nsec + (double)(curticks % tps) * ticks2nano; if (!(spec->tv_nsec < exp9)) { spec->tv_sec++; spec->tv_nsec -=exp9; } return 0; } 

我使用QueryPerformanceCounter() 改进clock_gettime()版本。

 #define BILLION (1E9) static BOOL g_first_time = 1; static LARGE_INTEGER g_counts_per_sec; int clock_gettime(int dummy, struct timespec *ct) { LARGE_INTEGER count; if (g_first_time) { g_first_time = 0; if (0 == QueryPerformanceFrequency(&g_counts_per_sec)) { g_counts_per_sec.QuadPart = 0; } } if ((NULL == ct) || (g_counts_per_sec.QuadPart <= 0) || (0 == QueryPerformanceCounter(&count))) { return -1; } ct->tv_sec = count.QuadPart / g_counts_per_sec.QuadPart; ct->tv_nsec = ((count.QuadPart % g_counts_per_sec.QuadPart) * BILLION) / g_counts_per_sec.QuadPart; return 0; } 

我认为我的版本是对使用QueryPerformanceCounter()目前接受的答案的改进,因为 –

  1. 更健壮 – 检查函数的返回值,也是通过引用变量返回的值。
  2. 更强大 – 检查输入参数的有效性。
  3. 更简化 – 使用尽可能少的变量(3对7)。
  4. 更简化 – 避免涉及GetSystemTimeAsFileTime()的代码路径,因为QueryPerformanceFrequency()和QueryPerformanceCounter()保证可以在运行Windows XP或更高版本的系统上运行

您可以使用timespec_get来实现简单的clock_gettime。
(自C11开始, timespec_get函数可用)

 int clock_gettime(int, struct timespec *tv) { return timespec_get(tv, TIME_UTC); } 

…但结果timespec在我的Windows7 64位机器上的分辨率约为10毫微米。 🙁

这是我的clock_gettime版本。

 int clock_gettime(int, struct timespec *tv) { static int initialized = 0; static LARGE_INTEGER freq, startCount; static struct timespec tv_start; LARGE_INTEGER curCount; time_t sec_part; long nsec_part; if (!initialized) { QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&startCount); timespec_get(&tv_start, TIME_UTC); initialized = 1; } QueryPerformanceCounter(&curCount); curCount.QuadPart -= startCount.QuadPart; sec_part = curCount.QuadPart / freq.QuadPart; nsec_part = (long)((curCount.QuadPart - (sec_part * freq.QuadPart)) * 1000000000UL / freq.QuadPart); tv->tv_sec = tv_start.tv_sec + sec_part; tv->tv_nsec = tv_start.tv_nsec + nsec_part; if(tv->tv_nsec >= 1000000000UL) { tv->tv_sec += 1; tv->tv_nsec -= 1000000000UL; } return 0; }