25

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

Now i want to port above code to windows. can any one provide sample code.

Thanks!

pmg
  • 98,431
  • 10
  • 118
  • 189
venkysmarty
  • 10,013
  • 19
  • 87
  • 165
  • 1
    check some options at http://stackoverflow.com/questions/275004/c-timer-function-to-provide-time-in-nano-seconds – pmg Mar 23 '11 at 11:20

6 Answers6

40

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 <<= 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);
}
Carl Staelin
  • 1,039
  • 10
  • 9
  • 1
    whow... You had this code ready, hadn't you? I like the idea of just hijacking the `clock_gettime` function. – xtofl Mar 23 '11 at 12:27
  • Yes --- this was code I wrote as part of a port of lmbench to Windows – Carl Staelin May 16 '11 at 12:36
  • 2
    Thanks for that snippet. I get an error `cannot convert 'timespec*' to 'timeval*' for argument '2' to 'int clock_gettime(int, timeval*)` when trying to crosscompile your code using `mingw`.. what am I missing here? – a1337q Jan 11 '13 at 10:44
  • apparently windows timeval structure does not go beyond microseconds, whereas linux timeval uses nanoseconds instead, is it possible to support nanosecond on windows? – Salepate Nov 05 '13 at 17:57
  • @Salepate - Linux timeval also uses microseconds. See this link: http://linux.die.net/man/2/gettimeofday – Aravind Dec 19 '13 at 09:43
  • 4
    this code shows time relative to program start, not real clock time. it shows important functions but IS NOT replacement for clock_gettime !!! – Asain Kujovic Jul 09 '15 at 06:32
  • Have you ever come across a system where `QueryPerformanceFrequency()` returned **False**? – work.bin Jul 05 '16 at 17:42
  • 1
    What is the value of X ? – Omar Mar 08 '17 at 12:28
17

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 with impressive 100ns precision (1ms/10000).

And QPC-based solution which precision will be possibly (on some hw) even better 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 < exp9)) { spec->tv_sec++; spec->tv_nsec -=exp9; }
   return 0;
}
Asain Kujovic
  • 1,374
  • 11
  • 18
  • 5
    Documentation for the FILETIME structure [here](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx) says "Do not cast a pointer to a FILETIME structure to either a ULARGE_INTEGER* or __int64* value because it can cause alignment faults on 64-bit Windows." – Spencer Sep 03 '15 at 17:04
  • You're a savior. This was the only thing standing between my Windows machine and a Linux-targeted C99 library :) – Violet Giraffe Jul 22 '16 at 21:03
  • 1
    @Spencer it is &__int64 casted to FILETIME*, not oposite direction, so isn't it always aligned well to 8 bytes. – Asain Kujovic Jul 27 '16 at 14:50
  • could you explain how the QPC can be translated to a REALTIME? I think this answer is incorrect. According to the docs QPC retrieves the monotonic clock that is neither adjusted by NTP nor other adjustment processes – Robin F. Aug 09 '18 at 13:49
  • 1
    @RobinF. it takes current unix_time ONCE ... and calculate difference by QPC in next function-calls, using saved STATIC variables. – Asain Kujovic Aug 10 '18 at 09:28
  • @Spencer I think it is still a good answer if someone replaces pointer cast with `ULARGE_INTEGER` structure, before adding or subtracting from it. – guan boshen Jun 06 '19 at 15:14
2

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

I think my version is an improvement over the currently accepted answer using QueryPerformanceCounter(), because -

  1. More robust - checks return values of functions, also value returned in pass-by-reference variable.
  2. More robust - checks validity of input parameter.
  3. More streamlined - Uses as few as necessary number of variables (3 vs 7).
  4. More streamlined - Avoids the code-path involving GetSystemTimeAsFileTime() since QueryPerformanceFrequency() and QueryPerformanceCounter() are guaranteed to work on systems that run Windows XP or later.
work.bin
  • 1,048
  • 5
  • 25
2

A full-featured and fully-tested implementation of clock_gettime() has been in mingw-w64 for many years now. You'll have to use a toolchain with mingw64/msys2 to use this, with header #include <time.h> (on windows). If you're writing a codebase that's portable between linux and windows, and you can't find clock_gettime() in <time.h> for your linux builds 3, I'd suggest you try #include <pthread_time.h>, compiling with -pthread, or linking with -lrt.

See also question 60020968 for Windows builds; and 33846055, 538609 for your Linux builds.

  • 1
    I am a little green at the moment, I found that I needed to add `CFLAGS=-pthread` to mingw, which stumbled me because I kept expected to need `LDLIBS=-lpthread` which I did not need – ThorSummoner Jun 18 '20 at 20:13
  • Oh sorry, I now realise it's defined in time.h so you don't have to mess with pthreads at all! – Clark Thomborson Jun 20 '20 at 00:04
  • 1
    this seems relevant? https://github.com/Alexpux/mingw-w64/blob/6172d2f87e426462f89785753f1be553bd10fe2f/mingw-w64-headers/crt/time.h#L295 some extra conditions for getting clock_gettime declared by the time.h header – ThorSummoner Jun 20 '20 at 02:01
  • OK thanks, indeed clock_getttime() can be hard to find on a linux build, unless it's flagged for a POSIX compilation. That's somewhat off-topic here, as the question was about a Windows port of clock_gettime(); but then again why would you want to use the clock_gettime() interface on a Windows box unless you're writing portable code? Dividing by 1e6 is annoying -- and is probably unacceptably slow, if you're doing high-resolution timing. Poking around a bit more in StackOverflow just now I find others have had trouble accessing clock_gettime() on Linux builds – Clark Thomborson Jun 21 '20 at 07:33
0

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;
}
Woosung
  • 11
  • 1
0

I needed monotonic and realtime.

For monotonic, I just take the perf counter since a wall clock baseline is meaningless.

#define MS_PER_SEC      1000ULL     // MS = milliseconds
#define US_PER_MS       1000ULL     // US = microseconds
#define HNS_PER_US      10ULL       // HNS = hundred-nanoseconds (e.g., 1 hns = 100 ns)
#define NS_PER_US       1000ULL

#define HNS_PER_SEC     (MS_PER_SEC * US_PER_MS * HNS_PER_US)
#define NS_PER_HNS      (100ULL)    // NS = nanoseconds
#define NS_PER_SEC      (MS_PER_SEC * US_PER_MS * NS_PER_US)

int clock_gettime_monotonic(struct timespec *tv)
{
    static LARGE_INTEGER ticksPerSec;
    LARGE_INTEGER ticks;
    double seconds;

    if (!ticksPerSec.QuadPart) {
        QueryPerformanceFrequency(&ticksPerSec);
        if (!ticksPerSec.QuadPart) {
            errno = ENOTSUP;
            return -1;
        }
    }

    QueryPerformanceCounter(&ticks);

    seconds = (double) ticks.QuadPart / (double) ticksPerSec.QuadPart;
    tv->tv_sec = (time_t)seconds;
    tv->tv_nsec = (long)((ULONGLONG)(seconds * NS_PER_SEC) % NS_PER_SEC);

    return 0;
}

and wall clock, based on GMT unlike the tempting and similar _ftime() function.

int clock_gettime_realtime(struct timespec *tv)
{
    FILETIME ft;
    ULARGE_INTEGER hnsTime;

    GetSystemTimeAsFileTime(&ft);

    hnsTime.LowPart = ft.dwLowDateTime;
    hnsTime.HighPart = ft.dwHighDateTime;

    // To get POSIX Epoch as baseline, subtract the number of hns intervals from Jan 1, 1601 to Jan 1, 1970.
    hnsTime.QuadPart -= (11644473600ULL * HNS_PER_SEC);

    // modulus by hns intervals per second first, then convert to ns, as not to lose resolution
    tv->tv_nsec = (long) ((hnsTime.QuadPart % HNS_PER_SEC) * NS_PER_HNS);
    tv->tv_sec = (long) (hnsTime.QuadPart / HNS_PER_SEC);

    return 0;
}

And then the POSIX compatible function... see POSIX header for typedef and macros.

int clock_gettime(clockid_t type, struct timespec *tp)
{
    if (type == CLOCK_MONOTONIC)
    {
        return clock_gettime_monotonic(tp);
    }
    else if (type == CLOCK_REALTIME)
    {
        return clock_gettime_realtime(tp);
    }

    errno = ENOTSUP;
    return -1;
}
jws
  • 1,240
  • 9
  • 20