29

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
  • 106,608
  • 13
  • 126
  • 198
venkysmarty
  • 11,099
  • 25
  • 101
  • 184
  • 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

41

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,067
  • 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
  • 3
    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
  • 2
    What is the value of X ? – mmain Mar 08 '17 at 12:28
20

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,700
  • 13
  • 19
  • 6
    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
  • 2
    @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
  • 1
    "with impressive 100ns precision (1ms/10000)". It's the resolution, not precision. `GetSystemTimeAsFileTime` has a pretty horrible precision of ~15 ms (yes, milliseconds). – ScumCoder Dec 09 '22 at 21:09
  • "reliable and correct porting solution". I'm pretty sure a reliable and correct porting solution would check the first argument of `clock_gettime`, instead of not even assigning it a name, and act accordingly. A considerable portion of `clock_gettime` use cases need monotonic time (and thus supply `CLOCK_MONOTONIC`), which is _not_ what `GetSystemTimeAsFileTime` is (it suffers NTP adjustments and might very well give negative deltas). – ScumCoder Dec 09 '22 at 21:14
  • @ScumCoder precision and resolution are interchangeabe words (see linux man page of cockgettime)... naming variable that can not be implemented well on windows is deceiving practice... if you read that win8 added word precise to getsystimeasfiletime it still does not count as something usefull to the subject until you create a loop and examine the results with the old function (10ns tested well 7 years ago)... both above porting functions are great solution if you have some linux project and want to make it work on messy windows api. – Asain Kujovic Dec 14 '22 at 07:18
5

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;

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

    QueryPerformanceCounter(&ticks);

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

    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;

    GetSystemTimePreciseAsFileTime(&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
  • 2,171
  • 19
  • 30
  • As of now, this is the only correct answer in this whole thread. – ScumCoder Dec 10 '22 at 15:25
  • I was poked and reviewed my answer. There is now `GetSystemTimePreciseAsFileTime()` to use in `clock_gettime_realtime`. Also in theory `clock_gettime_monotonic()` should use `long double` to support the full 64-bit perf counter range without losing resolution. In practice it works with `double` based on sufficient unused bits. – jws Dec 11 '22 at 13:47
  • 1
    Just to clarify: `GetSystemTimePreciseAsFileTime` is unavailable before Windows 8, and `long double` is just a synonym for `double` if you use MSVC. – ScumCoder Dec 11 '22 at 14:10
  • Wow another controversial decision on `long double`... I will get rid of the `double`. – jws Dec 11 '22 at 19:40
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 <= 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,078
  • 7
  • 29
3

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
  • 1
    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
  • 31
  • 3