2011-03-23 3 views
15

У меня есть следующий код, выполняющийся на qnx momemntics.Портирование clock_gettime в windows

#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; 
} 

Теперь я хочу переместить над кодом в окна. может ли кто-нибудь предоставить пример кода.

Спасибо!

+1

проверить некоторые варианты на http://stackoverflow.com/questions/275004/c-timer-function-to-provide-time-in-nano-seconds – pmg

ответ

31

Вы можете реализовать 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); 
} 
+0

whow ... Вы имели этот код готов, hadn Не так ли? Мне нравится идея просто захватить функцию 'clock_gettime'. – xtofl

+0

Да --- это был код, который я написал как часть порта lmbench для Windows –

+2

Спасибо за этот фрагмент. Я получаю ошибку 'can not convert 'timespec *' to 'timeval *' для аргумента '2' to 'int clock_gettime (int, timeval *)' при попытке перекрестного компиляции кода с помощью 'mingw' .. что мне здесь не хватает? – a1337q

8

избежать 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; 
} 
+4

Документация для структуры FILETIME [здесь] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx) говорит: «Не накладывайте указатель на структуру FILETIME на ULARGE_INTEGER * или __int64 *, поскольку это может привести к ошибкам выравнивания в 64-битной Windows ». – Spencer

+0

Ты спаситель. Это была единственная вещь, стоящая между моей машиной Windows и Linux-ориентированной C99-библиотекой :) –

+1

@Spencer it & __ int64 отсылается в FILETIME *, а не в направлении oposite, поэтому он не всегда хорошо выравнивается до 8 байтов. –

-1

Вы можете использовать timespec_get реализовать простую clock_gettime.
(timespec_get функция доступна начиная с С11)

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

... но результат TimeSpec имеет около 10, мс разрешение на моем windows7 64-битной машине. :(

Вот моя версия 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; 
} 
+1

timespec_get() недоступен в VS 2013, Windows 8. –

2

Мои улучшили версию clock_gettime() с помощью 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 <= 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. Более надежный - проверяет возвращаемые значения функций, а также значение, возвращаемое в переменной pass-by-reference.
  2. Более надежный - проверяет правильность входного параметра.
  3. Больше обтекаемого - используется всего лишь необходимое количество переменных (3 против 7).
  4. более обтекаемым - Избегает код-пути с участием GetSystemTimeAsFileTime() так QueryPerformanceFrequency() и QueryPerformanceCounter() гарантированно работают на системах, работающих в Windows XP или более поздней версии.
+0

Это не компиляция с компилятором MSVC2015. Вы забыли добавить все свои предложения? Я хотел бы попробовать это, если это возможно. –

+1

Я не показывал включений в фрагменте, но он требует заголовка, упомянутого здесь - https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx , –

+0

Удивительный! Ty для обновления, work.bin! Я проверю это^_^ –

Смежные вопросы