可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have the following code running on 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
Now i want to port above code to windows. can any one provide sample code.
Thanks!
回答1:
You can implement a clock_gettime() replacement for windows as follows:
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 tv_sec = t.QuadPart / 1000000; tv->tv_usec = t.QuadPart % 1000000; return (0); }
回答2:
Avoiding PerformanceCounter mess, simple code:
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; }
...is fast, reliable and correct porting solution when high precision is not so important.
And QPC-based solution with full precision is:
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 tv_sec++; spec->tv_nsec -=exp9; } return 0; }
回答3:
My improved version of clock_gettime()
using QueryPerformanceCounter()
.
#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 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; }
I think my version is an improvement over the currently accepted answer using QueryPerformanceCounter()
, because -
- More robust - checks return values of functions, also value returned in pass-by-reference variable.
- More robust - checks validity of input parameter.
- More streamlined - Uses as few as necessary number of variables (3 vs 7).
- More streamlined - Avoids the code-path involving
GetSystemTimeAsFileTime()
since QueryPerformanceFrequency() and QueryPerformanceCounter() are guaranteed to work on systems that run Windows XP or later.
回答4:
You can use timespec_get to implement simple clock_gettime.
(timespec_get function is available since C11)
int clock_gettime(int, struct timespec *tv) { return timespec_get(tv, TIME_UTC); }
... but result timespec has about 10 milisec resolution on my windows7 64bit machine. :(
Here is my version of 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; }