Tracking Time

Started by
7 comments, last by jamesleighe 12 years, 9 months ago
[font="Arial"](Win32, DirectX, C++)

Q1)
I use [/font][font="Arial"]QueryPerformanceCounter to sample the current cycle count every frame, and take the difference of that and last frames cycle count to calculate the time delta of the current frame.[/font][font="Arial"]

[/font][font="Arial"]Ok, but the issue is that eventually the number returned by [/font][font="Arial"]QueryPerformanceCounter will loop back around to zero and mess stuff up...[/font][font="Arial"]

[/font] [font="Arial"]I'm guessing I just need to have a check that detects such things and prevent it from going through. Is this what I should do?[/font][font="Arial"]

[/font][font="Arial"]Q2)[/font][font="Arial"]
[/font][font="Arial"]I need to timestamp some things for various reasons and I figure the best way is to timestamp them with the time since the game started...[/font][font="Arial"]

[/font] [font="Arial"]This would involve keeping the cycle count of the first frame around and subtracting the cycle count of the current frame to calculate the 'time'.[/font][font="Arial"] [/font][font="Arial"]Is this how you guys would track time?[/font][font="Arial"]

[/font] [font="Arial"]Thanks as usual![/font]
Advertisement
This is how I usually calculate my frame time (i get back a result in seconds):

Init step:


LARGE_INTEGER startFrameTime;
LARGE_INTEGER endFrameTime;
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);

In main loop:

QueryPerformanceCounter(&startFrameTime);

...frame stuff...

QueryPerformanceCounter(&endFrameTime);

// calculate frame time
LONGLONG timeDiff = endFrameTime.QuadPart - startFrameTime.QuadPart;
frameTime = (float)timeDiff / (float)frequency.QuadPart;
I do the same thing (exept I use the inverse of frequency so I can multiply)...

But my questions were:
What to do when the results loop back around?
How do you track some kind of absolute time that you can use as a timestamp? (with similar ussues with looping back around)
If you get an endFrameTime that is less than a startFrameTime, I think you could calculate the timeDiff by:

[max LARGE_INTEGER value] - startFrameTime + endFrameTime

If you get an endFrameTime that is less than a startFrameTime, I think you could calculate the timeDiff by:

[max LARGE_INTEGER value] - startFrameTime + endFrameTime


Derp of cource!

EDIT: But, when tracking absolute time (time since the game started) the issue becomes more complicated. Also, even the floats will overflow eventually.
Not much of a problem for a client, since they may never play that long, but a server it will be serious.
If the problem is serious enough (running a server for years?) then you could always increment something when you roll over. Also, you don't need to store the ticks, you can convert the delta time to milliseconds before doing an offset, so that you get plenty of playing time.
Also, you don't need to store the ticks, you can convert the delta time to milliseconds before doing an offset, so that you get plenty of playing time.


Could you please elaborate on what you mean here?

EDIT: I'm not sure what you mean by offset pretty much. Also, if you mean add the delta to the absolute time instead of storing the first cycle count, I COULD do that but it would get really inaccurate as the number I was adding somthing small to got larger.
[font="Arial"]Q1) I use [/font][font="Arial"]QueryPerformanceCounter to sample the current cycle count every frame, and take the difference of that and last frames cycle count to calculate the time delta of the current frame.[/font] [font="Arial"]Ok, but the issue is that eventually the number returned by [/font][font="Arial"]QueryPerformanceCounter will loop back around to zero and mess stuff up...[/font] [font="Arial"]I'm guessing I just need to have a check that detects such things and prevent it from going through. Is this what I should do?[/font]

Without having seen your code I can almost guarantee that you are accidentally only using the lower part of the LARGE_INTEGER passed as an argument to QueryPerformanceCounter. The thing is that on a 3 GHz computer it would take 0xFFFFFFFFFFFFFFFF / 3,000,000,000 = 6148914691 seconds = 195 years for an unsigned LARGE_INTEGER to actually loop back to zero.

[font="Arial"]Q2)[/font] [font="Arial"]I need to timestamp some things for various reasons and I figure the best way is to timestamp them with the time since the game started...[/font] [font="Arial"]This would involve keeping the cycle count of the first frame around and subtracting the cycle count of the current frame to calculate the 'time'.[/font] [font="Arial"]Is this how you guys would track time?[/font] [font="Arial"]Thanks as usual![/font]

Personally I think using clock cycles to measure frame time sounds a little fanatical. Also, my own experience with performance counters is not particularly good, either, since the timer-system I wrote a while ago using them turned out to be so inaccurate it was downright useless (though this may not be the case on newer computers). Additionally, I think I once read something about these timers being even more inaccurate on laptops when these computers enter "low power mode" or something like that. My own advice would be to use timeGetTime or timeGetSystemTime since both these functions return the time since Windows started in milliseconds as a single 32-bit value (equivalent to a max session time of 1193 hours), which should be sufficiently accurate. And if you do so, be sure to call timeBeginPeriod somewhere in your program prior to using them with the smallest acceptable value (use timeGetDevCaps to find this) to ensure they are as precise as possible. Also remember to add winmm.lib to your library list when you link.
Just to clarify I don't use the cycles AS the frametime:


Sample_ ();
time_ = double(firstCycleCount_.QuadPart - lastCycleCount_.QuadPart) * invTicksPerSecond_;
timeDelta_ = double(currentCycleCount_.QuadPart - lastCycleCount_.QuadPart) * invTicksPerSecond_;


But it looks like all my questions have been answered, thanks guys.

FAKEDIT: I didn't realize it would take so long for a processor to loop back on an int64! Those things are monsters!
I would have to be tremendously unlucky to actually get caught in a loop-back so I'm not gona even bother coding for it.

This topic is closed to new replies.

Advertisement