Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm trying to do it using two FILETIMEs, casting them to ULONGLONGs, substracting the ULONGLONGs, and dividing the result by 10000. But it's pretty slow, and I want to know if there is a better way to do it.I use c++ with visual studio 2008 express edition. This is what I'm using:

FILETIME filetime,filetime2;
GetSystemTimeAsFileTime(&filetime);
Sleep(100);
GetSystemTimeAsFileTime(&filetime2);
ULONGLONG time1,time2;
time1 = (((ULONGLONG) filetime.dwHighDateTime) << 32) + filetime.dwLowDateTime;
time2 = (((ULONGLONG) filetime2.dwHighDateTime) << 32) + filetime2.dwLowDateTime;
printf("ELAPSED TIME IN MS:%d",(int)((time2-time1)/10000));
share|improve this question

4 Answers 4

up vote 3 down vote accepted

Use QueryPerformanceCounter.

long long milliseconds_now() {
    static LARGE_INTEGER s_frequency;
    static BOOL s_use_qpc = QueryPerformanceFrequency(&s_frequency);
    if (s_use_qpc) {
        LARGE_INTEGER now;
        QueryPerformanceCounter(&now);
        return (1000LL * now.QuadPart) / s_frequency.QuadPart;
    } else {
        return GetTickCount();
    }
}

// Somewhere else...
    // ...
    long long start = milliseconds_now();
    // ....
    long long elapsed = milliseconds_now() - start;
share|improve this answer
    
And would that run fast? –  XaitormanX Apr 4 '12 at 13:15
    
Fast enough to call a dozen times during a frame without noticeable impact. How many times do you expect to need it? –  user744 Apr 4 '12 at 13:21
    
about 4 times a frame. But if i put that code in a loop to do it 100 times, it takes about 10 seconds to execute, which is slow, why is this happening? –  XaitormanX Apr 4 '12 at 13:24
1  
You have a Sleep(100) in your code. It has nothing to do with the timers. –  user744 Apr 4 '12 at 13:28
1  
It ran fast on a p90 in 1996; I think it'll run fast enough today. ;) –  Darth Satan Apr 4 '12 at 18:17

Take a look at the GetTickCount() function it's return value is the number of milliseconds that have elapsed since the system was started.

unsigned int Last = 0;
unsigned int Now = 0;
Last = GetTickCount();
//...Run your functions..
Now = GetTickCount();
printf("Elapsed Time in Milliseconds: %i",(Now-Last));
share|improve this answer
6  
-1. GetTickCount() has poor resolution. –  user744 Apr 4 '12 at 13:11

To answer your question : there is no "best" solution to measure time. Every method has its own advantages/disadvantages. It all depends of your needs.

Here is several questions you should ask yourself before choosing one solution :

  • timer resolution. Do you really need a precise timer (< 1ms) or can you live with something less precise (eg : 10ms precision) ?

  • cpu cost. some methods will require more cpu than some others. generally more precise timers require more cpu. also, calling some methods can have consequences for the other applications (eg : calling timeBeginPeriod(1) in win32 stress the os and reduce laptop battery life)

  • works with SMP. some methods use specific CPU data (eg: number of cycles elapsed) and can have some problems in multiprocessor environments.

  • works with CPU that have power saving feature. Some cpu have ability to change frequency over the time, which can cause some trouble to some timing methods.

For the example you give, I would use a combination of QueryPerformanceCounter() / QueryPerformanceFrequency().

Also please note that in the example you give sleep(100) can actually wait more than 100ms. So even with very precise timer it can returns some results other than 100ms.

share|improve this answer
    
While it's true that some timing methods have problems on SMP, these are always bugs in the HAL, BIOS, or other driver-related problems, and must be fixed at that level. It's rare that you can solve the problem by switching to a different timing method. For example I've seen QPC run backwards because of bad drivers, but GetTickCount would have too - the only reason it didn't was because the jump was ~50µsec, so it didn't notice it at all. At best, your app can do a max call with the previously returned value. –  user744 Apr 4 '12 at 14:37
    
As it is, QPC and equivalent functions on other OSs like POSIX clock_gettime, are all specified to not run backwards even on SMP systems, and independent of current CPU frequency. So it's bad advice to caution people away from them and towards worse timing functions, because any other timing functions would likely suffer the same problems if you could ever get them to work as precisely as you wanted from QPC in the first place. So yeah, there is a best solution: QPC, clock_gettime, and mach_absolute_time. For game loop timing, there's no reason to use anything else if those are available. –  user744 Apr 4 '12 at 14:40

Generally timeGetTime() is best for timing game logic - GetTickCount isn't quite high enough resolution, and QPC & RDTSC are a lot more trouble than they are worth for that purpose.

For profiling on the other hand, either RDTSC or QPC can be quite worthwhile. I prefer RDTSC over QPC, though microsoft recommends QPC.

The four common time functions I use on win32:

GetTickCount() returns the current time in milliseconds relative to some arbitrary zero (usually, though not always system boot time), as a 32 bit integer (so it wraps every 49 days or so). It is usually the fastest method to measure a time. Unfortunately it is low resolution - typically it only updates 64 times per second. Contrary to popular rumor, calling timeBeginPeriod(1) will not increase its resolution on any system I've tested that on. There is also a 64 bit variant if you're worried about it wrapping.

timeGetTime() returns the current time in milliseconds relative to some arbitrary zero, as a 32 bit value (so it wraps after 49 days or so). It's not as fast as GetTickCount, but still pretty reasonable. It can be accurate to a single millisecond, though that may require calling timeBeginPeriod(1) first. Using timeGetTime requires linking against winmm.lib and including Mmsystem.h.

QueryPerformanceCounter() returns the current time in arbitrary units as a 64 bit integer. You can figure out what the units are by calling QueryPerformanceFrequency(), and the units will not change (absent a reboot). The underlying implementation of this varies widely, and each implementation has its own quirks and bugs that may occur on some hardware, making this obnoxious to use in widely deployed applications. Some implementations are very slow, others are reasonable, though none are as fast as GetTickCount or even timeGetTime. Typically timing resolution is better than 1 microsecond, though not necessarily much better.

RDTSC is an x86 / x64 assembly language opcode that returns the current time in units of CPU cycles (ie as a 64 bit integer. On some compilers it can be accessed as an intrinsic (__rdstc), on others you'll need inline asm. Its speed varies a bit between CPUs but is usually pretty reasonable - typically significantly faster than QueryPerformanceCounter but not as fast as GetTickCount. Unfortunately it has a few quirks - not as many as QueryPerformanceCounter, but still a lot more than the lower resolution time functions. It can sometimes run backwards on multicore CPUs when you switch cores due to imperfect synchronization between cores, the units are difficult to figure out, and the units can change in mid-timing due to power management changing the rate of the CPU clock.

Note that each of these four methods can drift relative to the other three - there is no clear authoritative flow of time.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.