Timing

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Hello i have some questions about timing..

      in particular
      timeBeginPeriod();
      timeEndPeriod();

      and their effect on timeGetTime();

      I know that there is some more accurate timers out their.. but i dont particularily feel like delving into assembly code(im just making tetris for something to do while i'm on coop )
      Bakka mitai!!!
    • A quick romp through Google groups comes up inconclusive. Without performing experiments myself, I can't tell you anything.

      timeGetTime is a reasonably good timer, down to about 1ms on the Windows platform, without getting into some assembly level timers.

      I can tell you that 1ms ain't good enough for profiling games - if you want 60fps you are already down to 0.016 seconds for each frame. You'll want something a lot tighter.

      Check this out: devx.com/SummitDays/Article/16293/2213?pf=true

      Perhaps that will work for you.
      Mr.Mike
      Author, Programmer, Brewer, Patriot
    • I use the method described here . Basically, it relies on the fact that most modern PCs have a high resolution performance counter, with a resolution in microseconds. It does fall back on timeGetTime in the unlikely event of the host machine having no performance counter.
      And there is no assembly involved :]
      pan narrans
    • Nice web site

      That's a good web site - Angel Code. One note about ticking the game's framerate at a constant - you should also do that when the game is being debugged. Wierd things happen when you send in 345.23 seconds into your main game loop's DeltaSeconds parameter.....
      Mr.Mike
      Author, Programmer, Brewer, Patriot
    • RE: Nice web site

      I learned something about timeBeginPeriod and timeEndPeriod.

      You can use them in conjunction with timeGetTime
      to make timeGetTime *actually* precise to 1ms

      apparently on most of the windows OS's timeGetTime can be off by up to 8ms
      ........................................................
      which is quite a lot to be off by considering..

      I also looked up some stuff about the performance counter funcs...

      i saw a really interesting function that used sleep(0)
      for the last millisecond of the timer.. the rest of it used timeGetTime.. it looked like it would work really well.. but unfortunately i lost the URL and i cant remember the specifics:(
      Bakka mitai!!!
    • WOW, okay, I'm giving you your profile rating now, your getting a 10 just for that link (although you have done plenty more to deserve it)... Heh heh, looks like somebody has beaten me to it, not that I'm surprised.

      Where were you earlier this year when I was looking for something like this? ;) (if you do have a look at the link, please excuse my embarrassing lack of knowledge, it was a long time ago and I know a lot more now. :O)

      Thanx too to Mr. Mike, for reminding me that I needed to find out what "profiling" meant. I have been doing it for as long as I remember, but didn't know it had a name.
    • RE: member ratings

      Originally posted by pan narrans
      Thanx!! I didn't even know about the rating system... d'oh!


      Yeah I know, it's hidden pretty well, I was just browsing the message board FAQ yesterday and came across it. I was planning on getting to know people for a couple of months before doing any ratings, but that link was just too damn good.

      The post was edited 1 time, last by Gerry ().

    • Actually, there's a few good articles out there, the one I like the most is this one by Robert Dunlop (it gets right to the point):
      mvps.org/directx/articles/selecting_timer_functions.htm
      There's also this one:
      geisswerks.com/ryan/FAQS/timing.html

      I hope this info helps!

      p.s. -- a Google search for "timegettime gettickcount queryperformancecounter" yields both these articles, but only by the 3rd page. Goes to show ya that Google isn't 100% perfect in ranking search hits (unless you change the search params to "English" and "15 hits per page" and THEN it's on the first page). Hmm... I guess this postscript counts as "too much information", eh? :)
    • Timer Class

      Here is the Timer class I use... I believe it is accurate to 1/100th of a nanosecond... and that's pretty good.

      The Timer Header Code:

      C Source Code

      1. /* 'Timer.h' */
      2. #include <windows.h>
      3. #include <time.h>
      4. /* Include this file only once */
      5. #pragma once
      6. /* Timer Class */
      7. class Timer
      8. {
      9. protected:
      10. /* Hardware timer variables */
      11. LARGE_INTEGER m_iFrequency;
      12. LARGE_INTEGER m_iLastQuery;
      13. LARGE_INTEGER m_iDelta;
      14. /* Time and date variables */
      15. tm * m_pkTime;
      16. public:
      17. /* Constructor / Destructor */
      18. Timer (void);
      19. ~Timer (void);
      20. /* Update the time variables */
      21. void Update (void);
      22. /* Return the timer information */
      23. float GetDelta (void);
      24. unsigned long GetSeconds (void);
      25. unsigned long GetMinutes (void);
      26. unsigned long GetHours (void);
      27. unsigned long GetDay (void);
      28. unsigned long GetMonth (void);
      29. unsigned long GetYear (void);
      30. };
      Display All


      Now the Timer.cpp Code:

      C Source Code

      1. /* 'Timer.cpp' */
      2. /* Complement header file */
      3. #include "Timer.h"
      4. /* Default constructor */
      5. Timer::Timer (void)
      6. {
      7. /* Get the hardware clock frequency and current count */
      8. QueryPerformanceFrequency (&m_iFrequency);
      9. QueryPerformanceCounter (&m_iLastQuery);
      10. }
      11. /* Default destructor */
      12. Timer::~Timer (void)
      13. {
      14. m_iFrequency.QuadPart = 0;
      15. m_iLastQuery.QuadPart = 0;
      16. }
      17. /* Update timer */
      18. void Timer::Update (void)
      19. {
      20. LARGE_INTEGER kTempTimer;
      21. time_t iTempTimeDate;
      22. /* Get current timer information and calculate difference */
      23. QueryPerformanceCounter (&kTempTimer);
      24. m_iDelta.QuadPart = kTempTimer.QuadPart - m_iLastQuery.QuadPart;
      25. /* Save current timer information */
      26. m_iLastQuery.QuadPart = kTempTimer.QuadPart;
      27. /* Get current time and date */
      28. time (&iTempTimeDate);
      29. m_pkTime = localtime (&iTempTimeDate);
      30. }
      31. /* Get delta time from last update */
      32. float Timer::GetDelta (void)
      33. {
      34. /* Convert to float and calculate delta in seconds */
      35. return (float)(m_iDelta.QuadPart) /
      36. (float)(m_iFrequency.QuadPart);
      37. }
      38. /* Get system seconds */
      39. unsigned long Timer::GetSeconds (void)
      40. {
      41. return m_pkTime->tm_sec;
      42. }
      43. /* Get system minutes */
      44. unsigned long Timer::GetMinutes (void)
      45. {
      46. return m_pkTime->tm_min;
      47. }
      48. /* Get system hours */
      49. unsigned long Timer::GetHours (void)
      50. {
      51. return m_pkTime->tm_hour;
      52. }
      53. /* Get system day */
      54. unsigned long Timer::GetDay (void)
      55. {
      56. return m_pkTime->tm_mday;
      57. }
      58. /* Get system month */
      59. unsigned long Timer::GetMonth (void)
      60. {
      61. return m_pkTime->tm_mon;
      62. }
      63. /* Get system year */
      64. unsigned long Timer::GetYear (void)
      65. {
      66. return m_pkTime->tm_year;
      67. }
      Display All


      And here is an example of how to use it:

      C Source Code

      1. #include <iostream>
      2. #include "Timer.h"
      3. using namespace std;
      4. int main(void)
      5. {
      6. Timer Time;
      7. float Delta1, Delta2;
      8. Time.Update();
      9. Delta1 = Time.GetDelta();
      10. cout << "Delta1: " << Delta1 << endl;
      Display All


      The above creates an instance of the class and two floats to record the changes. Time.Update() catches the difference in time since the last Time.Update(). Note: The constructor essentially does a Time.Update() itself also. Therefore, the first Delta1 measures the amount of time since Time was constructed until the first Time.Update(). I get a value of: 1.39683e-006 seconds... so approximately 1.4 microseconds. This is how long it took to construct the two float variables. Next:

      Source Code

      1. Time.Update();
      2. Delta2 = Time.GetDelta();
      3. cout << "Delta2: " << Delta2 << endl;


      This Time.Update() gets a new Delta2 which now was the measure of everything since the last Time.Update; therefore, the measure of how long it took the system to load the last delta into Delta1, and cout the information to the console window. Finally we have:

      Source Code

      1. cin.get();
      2. return EXIT_SUCCESS;
      3. }


      I hope this helps :)

      Nos
    • Has anyone read this yet?

      support.microsoft.com/default.aspx?scid=kb;en-us;274323

      It's an MSDN Knowledge Base Article that discusses the problem that the result returned from QueryPerformanceCounter may unexpectedly leap forwards from time to time.

      Also there's a pretty high overhead involved in calling QueryPerformanceCounter and QueryPerformanceFrequency - it's supposed to call a couple of DLLs or something like that.

      The best way AFAIK is to use the Read Timestamp Counter (RDTSC) assembly instruction.
    • I also have a timer using the Windows High performance Hardware Timers, and also uses the unix equivelent if on a Unix machine, if anyone wants to use it PM me.
      PC - Custom Built
      CPU: 3rd Gen. Intel i7 3770 3.4Ghz
      GPU: ATI Radeon HD 7959 3GB
      RAM: 16GB

      Laptop - Alienware M17x
      CPU: 3rd Gen. Intel i7 - Ivy Bridge
      GPU: NVIDIA GeForce GTX 660M - 2GB GDDR5
      RAM: 8GB Dual Channel DDR3 @ 1600mhz
    • Hey guys,

      I had recieved a PM asking about my timer, so I thought I would share my response as it explains hardware timers a bit (as far as I understand them) and I thought others would benefit from it.

      ---------------------------------------


      The timer class I have utilizes two different sets of functions depending on the target platform, they both utilize the hardware timer built into virtually every modern CPU on the market.

      On Unix based systems this hardware timer can be accessed using the gettimeofday function and timeval struct.

      On Windows based systems the hardware timer is accessed through QueryPerformanceCounter and QueryPerformanceFrequency, which is possibly more acurate as you are able to determine the exact frequency in Hz that the timer operates on.

      The accuracy of these timers is different, gettimeofday gives you microseconds, and QueryPerformanceCounter is dependant on the frequency of the hardware, so more then a game will ever need, however the performance is very good due to the fact that hardware is used.

      I will not share my entire code as I would have to copy it to paste bin, and it may not help you out in actually learning it, but I will write up a quick timer for you using the Windows based setup.

      Brainfuck Source Code

      1. //These variables are all you need for a basic timer, they should be members of your class
      2. //Last time is used to track the last time in 'counts', Frequency is the time it takes per 'count', deltaTime is the time since the last frame 1.0 being a second, timescale converts your time differential into seconds
      3. long long m_nLastTime, m_nFrequency;
      4. double m_nDeltaTime, m_nTimeScale;
      5. //---------This code block should be part of your initialization function, ------------
      6. //This function determines the frequency (time per count) of the hardware timer, it usually results in nanosecond resolution
      7. QueryPerformanceFrequency((LARGE_INTEGER*)&m_nFrequency);
      8. //This function actually queries the current value of the timer, its best to do this at initialization as well
      9. QueryPerformanceCounter((LARGE_INTEGER*)&m_nLastTime);
      10. //This will give you the time scale to multiply your integer current time by which will give you a floating point number in seconds.
      11. m_nTimeScale = 1.0 / m_nFrequency;
      12. //--------------------------------------------------------------------------------------------------------
      13. //---------------This code block will be called every frame in an 'update' function of your class
      14. unsigned long long nCurrentTime;
      15. QueryPerformanceCounter((LARGE_INTEGER*)&nCurrentTime);
      16. m_nDeltaTime = (double)(nCurrentTime - m_nLastTime) * m_nTimeScale;
      17. m_nLastTime = nCurrentTime;
      Display All


      Essentially what you are doing here is first retrieving the value you need to calculate your time scale, this time scale is used to multiply the hardware timers current 'count' into a double precision floating point number representing the delta time in seconds. Each frame you will update your timer class by retrieving the current time with QueryPerformanceCounter into a temporary variable, to calculate the delta time you will subtract the 'last' time by the 'current' time, giving you the differential between the current frame update and the last time update, then multiplying this value by the time scale will give you the delta time in seconds. You then need to be sure to set the 'last' time variable to the 'current' time variable.

      If you desire to have a cross platform hardware timer, you will have to use some pre-processor blocking as windows does not have the <sys/time.h> headers as they are made for unix , there is a <time.h> however that is not the same thing. Essentially you will use the same process, however you use the gettimeofday function passing a temporary timeval struct as a parameter. This struct will now have both the seconds, and the microseconds available to grab, you will want to use the microseconds for your calculations, and your time scale will now simply be 'm_nTimeScale = 0.000001;'

      Let me know how this works out for you
      PC - Custom Built
      CPU: 3rd Gen. Intel i7 3770 3.4Ghz
      GPU: ATI Radeon HD 7959 3GB
      RAM: 16GB

      Laptop - Alienware M17x
      CPU: 3rd Gen. Intel i7 - Ivy Bridge
      GPU: NVIDIA GeForce GTX 660M - 2GB GDDR5
      RAM: 8GB Dual Channel DDR3 @ 1600mhz