Larry Osterman's WebLog

Confessions of an Old Fogey
Blog - Title

What’s the difference between GetTickCount and timeGetTime?

What’s the difference between GetTickCount and timeGetTime?

Rate This
  • Comments 26

I’ve always believed that the most frequently used multimedia API in winmm.dll was the PlaySound API.  However I recently was working with the results of some static analysis tools that were run on the Windows 7 codebase and I realized that in fact the most commonly used multimedia API (in terms of code breadth) was actually the timeGetTime API.  In fact almost all the multimedia APIs use timeGetTime which was somewhat surprising to me at the time.

The MSDN article for timeGetTime says that timeGetTime “retrieves the system time, in milliseconds. The system time is the time elapsed since the system started.”.

But that’s almost exactly what the GetTickCount API returns “the number of milliseconds that have elapsed since the system was started, up to 49.7 days.” (obviously timeGetTime has the same 49.7 day limit since both APIs return 32bit counts of milliseconds).

So why are all these multimedia APIs using timeGetTime and not GetTickCount since the two APIs apparently return the same value?  I wasn’t sure so I dug in a bit deeper.

The answer is that they don’t.  You can see this with a tiny program:

int _tmain(int argc, _TCHAR* argv[])
{
    int i = 100;
    DWORD lastTick = 0;
    DWORD lastTime = 0;
    while (--i)
    {
        DWORD tick = GetTickCount();
        DWORD time = timeGetTime();
        printf("Tick: %d, Time: %d, dTick: %3d, dTime: %3d\n", tick, time, tick-lastTick, time-lastTime);
        lastTick = tick;
        lastTime = time;
        Sleep(53);
    }
    return 0;
}

If you run this program, you’ll notice that the difference between the timeGetTime results is MUCH more stable than the difference between the GetTickCount results (note that the program sleeps for 53ms which usually doesn’t match the native system timer resolution):

Tick: 175650292, Time: 175650296, dTick:  46, dTime:  54
Tick: 175650355, Time: 175650351, dTick:  63, dTime:  55
Tick: 175650417, Time: 175650407, dTick:  62, dTime:  56
Tick: 175650464, Time: 175650462, dTick:  47, dTime:  55
Tick: 175650526, Time: 175650517, dTick:  62, dTime:  55
Tick: 175650573, Time: 175650573, dTick:  47, dTime:  56
Tick: 175650636, Time: 175650628, dTick:  63, dTime:  55
Tick: 175650682, Time: 175650683, dTick:  46, dTime:  55
Tick: 175650745, Time: 175650739, dTick:  63, dTime:  56
Tick: 175650792, Time: 175650794, dTick:  47, dTime:  55
Tick: 175650854, Time: 175650850, dTick:  62, dTime:  56

That’s because GetTickCount is incremented by the clock tick frequency on every clock tick and as such the delta values waver around the actual time (note that the deltas average to 55ms so on average getTickCount returns an accurate result but not with spot measurements) but timeGetTime’s delta is highly predictable.

It turns out that for isochronous applications (those that depend on clear timing) it is often important to be able to retrieve the current time in a fashion that doesn’t vary, that’s why those applications use timeGetTime to achieve their desired results.

  • So I'm curious... you say that GetTickCount is incremented by the clock tick; how does timeGetTime do it? (esp. since it's more accurate)

  • timeGetTime isn't necessarily more accurate, it's more regular.  

    Ultimately it's the difference between KeGetTickCount (http://msdn.microsoft.com/en-us/library/ms801938.aspx) and KeQueryInterruptTime (http://msdn.microsoft.com/en-us/library/ms801940.aspx) - This isn't 100% accurate but it's close enough.

  • Sooo.. what happens when you hit 49.7 days?

  • Glen: The count wraps of course.

  • There is another benefit of using timeGetTime() - you can improve the accuracy by calling timeBeginPeriod() if you need to.

  • With GetTickCount() you cannot measure time deltas less then 15-16 ms, while with timeGetTime() this is possible to get close to 1 ms precision (especially when using timeBeginPeriod(1)).

  • Adam: calling timeBeginPeriod increases the accuracy of GetTickCount as well.

    using timeBeginPeriod is a hideously bad idea in general - we've been actively removing all of the uses of it in Windows because of the power consumption consequences associated with using it.

    There are better ways of ensuring that your thread runs in a timely fashion.

  • "There are better ways of ensuring that your thread runs in a timely fashion."

    OK, now it's me who is curious: Which ones?

    I need a special thread to run every 40ms, target OSes are XP, Vista, and 7. Achieving this with a timer and timeBeginPeriod is what we do currently, what do you propose instead?

  • Ooh: If you want to run every 40ms, use timeBeginPeriod(40), not timeBeginPeriod(1).

    timeBeginPeriod(1) is evil.

  • Btw for XP, it doesn't really matter what you use - the power consumption on XP is so bad that timeBeginPeriod doesn't make a difference.

    Why do you need isoch behavior?  Most of the time isoch requirements are tied to multimedia rendering, is this the case for your solution?

  • timeGetTime is much better for off-the-cuff profiling.  Want to know how long a computation is taking, call timeGetTime before and after and subtract.  Of course using the performance counter is even more accurate, but slightly more difficult to use from script (you need to marshal a structure instead of a single 32-bit integer).

  • "using timeBeginPeriod is a hideously bad idea in general"

    But given a thread that needs to run every 4ms on XP/Vista/7, what are the alternatives?

  • Larry, out of interest could you quantify the "power consumption consequences associated with using it", are we talking halving the battery life here?  10% hit?

    And, other than power consumption, is there another reason to avoid timeBeginPeriod?

  • Kev: On XP there aren't any reasonable alternatives.  On Vista/7 I get back to the question I asked above: Why do you need isoch behavior?  What task are you performing that requires that level of accuracy?  Typically these kinds of tasks involve multimedia rendering and for those there are other solutions (like mmcss) which can generate similar levels of accuracy without sacrificing power.

  • Kev, it depends.  The CPU is being woken up between 10x and 15x as often but doing less work in each call.  The measurements we did in Win7 showed that it was significant.

Page 1 of 2 (26 items) 12