Cross-Platform High-Performance timing?

Started by
7 comments, last by Jan Wassenberg 15 years, 7 months ago
I was wondering if there's a cross-platform wrapper around high-performance timers like QueryPerfomanceTimer on windows, and whatever is used for that on linuxes. I did a search but couldn't find any.
Advertisement
I know about Boost::Timer, but I don't know its resolution...
glfw comes also with some timing functions. I have just looked into its source code and on windows it seems to use QueryPerformanceCounter if available with a fall-back to timeGetTime. On Linux and Mac it uses gettimeofday.
Thanks for your replies. Boost::Timer I knew of, but it seems low-resolution. GLFW I also knew of, but for some reason I wasn't using the high-precision timing stuff, only low-precision, so hadn't realized it had that as well.
Take a look at SDL_GetTicks source code.
I've seen things you people wouldn't believe. Attack ships on fire off the shoulder of Orion. I watched C-beams glitter in the dark near the Tannhauser gate. All those moments will be lost in time, like tears in rain. Time to die.
Quote:Take a look at SDL_GetTicks source code.

You mean
voidSDL_StartTicks(void){    /* Set first ticks value */#ifdef USE_GETTICKCOUNT    start = GetTickCount();#else#if 0                           /* Apparently there are problems with QPC on Win2K */    if (QueryPerformanceFrequency(&hires_ticks_per_second) == TRUE) {        hires_timer_available = TRUE;        QueryPerformanceCounter(&hires_start_ticks);    } else#endif    {        hires_timer_available = FALSE;        timeBeginPeriod(1);     /* use 1 ms timer precision */        start = timeGetTime();    }#endif}Uint32SDL_GetTicks(void){    DWORD now, ticks;#ifndef USE_GETTICKCOUNT    LARGE_INTEGER hires_now;#endif#ifdef USE_GETTICKCOUNT    now = GetTickCount();#else    if (hires_timer_available) {        QueryPerformanceCounter(&hires_now);        hires_now.QuadPart -= hires_start_ticks.QuadPart;        hires_now.QuadPart *= 1000;        hires_now.QuadPart /= hires_ticks_per_second.QuadPart;        return (DWORD) hires_now.QuadPart;    } else {        now = timeGetTime();    }#endif    if (now < start) {        ticks = (TIME_WRAP_VALUE - start) + now;    } else {        ticks = (now - start);    }    return (ticks);}


QueryPerformanceCounter is never called. Use QPC on Windows, and gettimeofday on POSIX, it isn't that hard to do it yourself. But beware of QPC!
You have other issues to worry about on Windows systems as well, especially if your program is running on multicore systems. Basically what can happen is QPC can get its timing information from different cores between calls to the function, and the timing information between cores is not guaranteed to be in sync with each other. You essentially have to lock your timing code to one core in order to get reliable, monotonic timing information. At least, this is the case on Windows XP. I've heard this issue has been fixed in Vista, but I haven't checked myself.

I've heard the same issues can persist on Linux systems as well since, at least on x86 systems, gettimeofday() I believe relies on the TSC, which may or may not be synced across cores. Instead, you can use clock_gettime() with CLOCK_MONOTONIC as the clock ID, and you're guaranteed to get monotonic time then. clock_getres() can tell you what the resolution of the timer is, but from what I've heard it's on par with gettimeofday(). Again, I haven't done many tests myself, but I do remember looking into this pretty heavily not too long ago as I was trying to figure out how to get reliable high performance timing on multiple platforms.
Yes, be careful of what romer is talking about. Pick a thread to run QPC on, and then use SetThreadAffinity to keep it on one core. Also make sure you have some code in place that will handle things gracefully in case you get a weird result that gives you a negative time delta (which can happen on some CPU's that use clock throttling).
As hinted at above, there are all kinds of pitfalls which are described in an article/thread. I've posted source code [1.6 MB] of a library that goes to quite some trouble (1.5 KLOC) to choose a safe timer. It makes your app source-code compatible with Unix gettimeofday and clock_gettime by emulating those on Windows.
Patches and suggestions for improvement are most welcome.
E8 17 00 42 CE DC D2 DC E4 EA C4 40 CA DA C2 D8 CC 40 CA D0 E8 40E0 CA CA 96 5B B0 16 50 D7 D4 02 B2 02 86 E2 CD 21 58 48 79 F2 C3

This topic is closed to new replies.

Advertisement