EAStopwatch.html 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head>
  2. <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
  3. <title>EARandom</title>
  4. <link type="text/css" rel="stylesheet" href="UTFDoc.css">
  5. <meta name="author" content="Paul Pedriana">
  6. </head>
  7. <body bgcolor="#FFFFFF">
  8. <h1>EAStopwatch</h1>
  9. <h2>Introduction</h2>
  10. <p>EAStopwatch provides timing facilities for use in game development. It provides
  11. two C++ classes:</p>
  12. <blockquote>
  13. <table width="100%" border="1">
  14. <tr>
  15. <td>Stopwatch</td>
  16. <td>A general-purpose timer</td>
  17. </tr>
  18. <tr>
  19. <td>LimitStopwatch</td>
  20. <td>A special-purpose countdown-style timer</td>
  21. </tr>
  22. </table>
  23. </blockquote>
  24. <p>Stopwatch acts much like and classic hand-held stopwatch or like the stopwatch
  25. found on sports watches. It has additional flexibility, such as the ability
  26. to set an elapsed time to any value.</p>
  27. <p>LimitStopwatch is a stopwatch which simply tells you if a given amount of time
  28. has passed. You can accomplish this same functionality by polling a Stopwatch,
  29. but LimitStopwatch is more efficient.</p>
  30. <h2>Important things to remember</h2>
  31. <ul>
  32. <li> You won't get very accurate timings if you use a millisecond stopwatch
  33. repeatedly to time tiny sections of code that take only nanoseconds.</li>
  34. <li>You can start and stop a stopwatch repeatedly and it will do the right thing,
  35. which is sum up the times during which it was running.</li>
  36. <li>Timing CPU cycles (clock ticks) accurately can be hard if you are trying
  37. to time very small pieces of code. Pipeline stalls and memory stalls can result
  38. in highly variable results.</li>
  39. <li>A running stopwatch consumes no resources (CPU cycles nor memory) during
  40. its existence nor while it is running.</li>
  41. <li>You don't have to stop a stopwatch that is running; it doesn't take up CPU
  42. time to be running. It is not an error to not stop a stopwatch.</li>
  43. <li>There is a distinction between stopwatch cycles and CPU-based cycles. While
  44. it may be the case that the stopwatch uses a CPU cycle counter as its basis,
  45. this also may not be the case. In fact, using a CPU cycles counter as the
  46. basis for a stopwatch is often a dangerous thing to do because processors
  47. these days will sometimes switch frequencies on the fly. </li>
  48. <li>You don't have to worry about multi-processor issues unless you are running
  49. on a desktop platform such as Windows. In the case of such platforms, you
  50. only need to worry about such issues if you happen to define EA_STOPWATCH_FORCE_CPU_CYCLE_USAGE = 1.</li>
  51. <li>You can call safely GetElapsedTime while the stopwatch is running; it will
  52. simply return the currently elapsed time.</li>
  53. <li>The construction and destruction instances of Stopwatch is fast; don't worry
  54. about it. Similarly, a Stopwatch instance is small in size.</li>
  55. </ul>
  56. <h2>Example usage </h2>
  57. <p>EAStopwatch is very easy to use, though curiously its simplicity actually confuses
  58. some users familiar with more cumbersome alternatives.</p>
  59. <p>Basic usage:</p>
  60. <pre class="code-example">Stopwatch stopwatch(Stopwatch::kUnitsMilliseconds);
  61. stopwatch.Start();
  62. DoSomethingThatYouWantToMeasure();
  63. printf("Time to do something: %u.\n", stopwatch.GetElapsedTime());</pre>
  64. Example of stopwatch reuse (via Restart):
  65. <pre class="code-example">Stopwatch stopwatch(Stopwatch::kUnitsCycles, true); // Note that 'true' tells the timer to auto-start here.
  66. DoSomethingSmall();
  67. printf("Time to do something small: %u.\n", stopwatch.GetElapsedTime());
  68. stopwatch.Restart();
  69. DoSomethingElseSmall();
  70. printf("Time to do something else small: %d.\n", stopwatch.GetElapsedTime());</pre>
  71. Example of SetElapsedTime usage.
  72. <pre class="code-example">Stopwatch stopwatch(Stopwatch::kUnitsMilliseconds);
  73. stopwatch.SetElapsedTime(100); // Give the stopwatch a &quot;100 ms head start.&quot;
  74. stopwatch.Start();
  75. printf("This should print out 100 (or maybe 101): %u.\n", stopwatch.GetElapsedTime());</pre>
  76. <p>Example of LimitStopwatch usage:</p>
  77. <pre class="code-example">LimitStopwatch limitStopwatch(Stopwatch::kUnitsMilliseconds, 1000, true);
  78. while(!limitStopwatch.IsTimeUp())
  79. printf("waiting\n"); </pre>
  80. <h2>Don't do this!</h2>
  81. <p> It seems that quite often people unfamiliar with a C++ stopwatch tend to revert
  82. away from using the stopwatch as it was designed and try to do timings manually,
  83. like shown below. The code below is more complicated than it needs to be and
  84. is less precise than it can be, as the high internal resolution of the stopwatch
  85. is lost when using it like this. </p>
  86. <pre class="code-example"><font color="#CC0000">Stopwatch stopwatch(Stopwatch::kUnitsMilliseconds);
  87. stopwatch.Start();
  88. uint64_t timeStart = stopwatch.GetElapsedTime();
  89. DoSomething();
  90. uint64_t timeElapsed = stopwatch.GetElapsedTime() - time;</font>
  91. </pre>
  92. <h2>Interface </h2>
  93. <p>Stopwatch</p>
  94. <pre class="code-example">class Stopwatch
  95. {
  96. public:
  97. <span class="code-example-comment"> /// Units
  98. /// Defines common timing units plus a user-definable set of units.
  99. </span> enum Units
  100. {
  101. kUnitsCycles = 0, <font color="#999999">/// Stopwatch clock ticks. </font>
  102. kUnitsCPUCycles = 1, <font color="#999999">/// CPU clock ticks (or similar equivalent for the platform).</font>
  103. kUnitsNanoseconds = 2, <font color="#999999">/// Count in nanoseconds.</font>
  104. kUnitsMicroseconds = 3, <font color="#999999">/// Count in microseconds.</font>
  105. kUnitsMilliseconds = 4, <font color="#999999">/// Count in milliseconds.</font>
  106. kUnitsSeconds = 5, <font color="#999999">/// Count in seconds.</font>
  107. kUnitsMinutes = 6, <font color="#999999">/// Count in minutes.</font>
  108. kUnitsUserDefined = 1000 <font color="#999999">/// User defined units (animation frames, video vertical retrace, etc.).</font>
  109. };
  110. public:
  111. <span class="code-example-comment"> /// Stopwatch
  112. /// Constructor for Stopwatch, allows user to specify units.
  113. /// If units are kUnitsUserDefined, you'll need to either subclass
  114. /// Stopwatch and implement GetUserDefinedStopwatchCycle or call
  115. /// SetUserDefinedUnitsToStopwatchCyclesRatio in order to allow it
  116. /// to know how to convert units.
  117. </span> explicit Stopwatch(int nUnits = kUnitsCycles, bool bStartImmediately = false);
  118. <span class="code-example-comment"> /// Stopwatch
  119. /// Copy constructor.
  120. </span> Stopwatch(const Stopwatch& stopwatch);
  121. <span class="code-example-comment"> /// ~Stopwatch
  122. /// Destructor.
  123. </span> ~Stopwatch();
  124. <span class="code-example-comment"> /// operator=
  125. /// Assignment operator.
  126. </span> Stopwatch& operator=(const Stopwatch& stopwatch);
  127. <span class="code-example-comment"> /// GetUnits
  128. /// Gets the current units. Returns one of enum Units or kUnitsUserDefined+.
  129. </span> int GetUnits() const;
  130. <span class="code-example-comment"> /// SetUnits
  131. /// Sets the current units. One of enum Units or kUnitsUserDefined+.
  132. </span> void SetUnits(int nUnits);
  133. <span class="code-example-comment"> /// Start
  134. /// Starts the stopwatch. Continues where it was last stopped.
  135. /// Does nothing if the stopwatch is already started.
  136. </span> void Start();
  137. <span class="code-example-comment"> /// Stop
  138. /// Stops the stopwatch it it was running and retaines the elasped time.
  139. </span> void Stop();
  140. <span class="code-example-comment"> /// Reset
  141. /// Stops the stopwatch if it was running and clears the elapsed time.
  142. </span> void Reset();
  143. <span class="code-example-comment"> /// Restart
  144. /// Clears the elapsed time and starts the stopwatch if it was not
  145. /// already running. Has the same effect as Reset(), Start().
  146. </span> void Restart();
  147. <span class="code-example-comment"> /// IsRunning
  148. /// Returns true if the stopwatch is running.
  149. </span> bool IsRunning() const;
  150. <span class="code-example-comment"> /// GetElapsedTime
  151. /// Gets the elapsed time, which properly takes into account any
  152. /// intervening stops and starts. Works properly whether the stopwatch
  153. /// is running or not.
  154. </span> uint64_t GetElapsedTime() const;
  155. <span class="code-example-comment"> /// SetElapsedTime
  156. /// Allows you to set the elapsed time. Erases whatever is current.
  157. /// Works properly whether the stopwatch is running or not.
  158. </span> void SetElapsedTime(uint64_t nElapsedTime);
  159. <span class="code-example-comment"> /// GetElapsedTimeFloat
  160. /// Float version, which is useful for counting fractions of
  161. /// seconds or possibly milliseconds.
  162. </span> float GetElapsedTimeFloat() const;
  163. <span class="code-example-comment"> /// SetElapsedTimeFloat
  164. /// Allows you to set the elapsed time. Erases whatever is current.
  165. /// Works properly whether the stopwatch is running or not.
  166. </span> void SetElapsedTimeFloat(float fElapsedTime);
  167. <span class="code-example-comment"> /// SetCyclesPerUnit
  168. /// Allows the user to manually override the frequency of the
  169. /// timer.
  170. </span> void SetCyclesPerUnit(float fCyclesPerUnit);
  171. <span class="code-example-comment"> /// GetCyclesPerUnit
  172. /// Returns the value number of cycles per unit. If the user
  173. /// set a manual value via SetCyclesPerUnit, this function returns
  174. /// that value.
  175. </span> float GetCyclesPerUnit() const;
  176. <span class="code-example-comment"> /// GetStopwatchCycle
  177. /// Gets the current stopwatch cycle on the current machine.
  178. /// Note that a stopwatch cyle may or may not be the same thing
  179. /// as a CPU cycle. We provide the distinction between stopwatch
  180. /// cycles and CPU cycles in order to accomodate platforms (e.g.
  181. /// desktop platforms) in which CPU cycle counting is unreliable.
  182. </span> static uint64_t GetStopwatchCycle();
  183. <span class="code-example-comment"> /// GetStopwatchFrequency
  184. /// Note that the stopwatch freqency may or may not be the same thing
  185. /// as the CPU freqency. We provide the distinction between stopwatch
  186. /// cycles and CPU cycles in order to accomodate platforms (e.g.
  187. /// desktop platforms) in which CPU cycle counting is unreliable.
  188. </span> static uint64_t GetStopwatchFrequency();
  189. <span class="code-example-comment"> /// GetUnitsPerStopwatchCycle
  190. /// Returns the number of stopwatch cycles per the given unit.
  191. /// If the unit is seconds, the return value would be the frequency of
  192. /// the stopwatch timer and thus be the same value as returned by
  193. /// GetStopwatchFrequency().
  194. </span> static float GetUnitsPerStopwatchCycle(Units units);
  195. <span class="code-example-comment"> /// GetCPUCycle
  196. /// Gets the current CPU-based timer cycle on the current processor
  197. /// (if in a multiprocessor system). Note that this doesn't necessarily
  198. /// get the actual machine CPU clock cycle; rather it returns the
  199. /// CPU-based timer cycle. One some platforms the CPU-based timer is
  200. /// a 1:1 relation to the CPU clock, while on others it is some multiple
  201. /// of it.
  202. </span> static uint64_t GetCPUCycle();
  203. <span class="code-example-comment"> /// GetCPUFrequency
  204. /// Gets the frequency of the CPU-based timer. Note that this doesn't
  205. /// necessarily get the actual machine CPU clock frequency; rather it returns
  206. /// the CPU-based timer frequency. One some platforms the CPU-based timer is
  207. /// a 1:1 relation to the CPU clock, while on others it is some multiple of it.
  208. </span> static uint64_t GetCPUFrequency();
  209. <span class="code-example-comment"> /// GetUnitsPerCPUCycle
  210. /// Returns the number of CPU cycles per the given unit.
  211. /// If the unit is seconds, the return value would be the frequency
  212. /// of the CPU-based timer.
  213. </span> static float GetUnitsPerCPUCycle(Units units);
  214. };
  215. </pre>
  216. <p>LimitStopwatch</p>
  217. <pre class="code-example">class LimitStopwatch : public Stopwatch
  218. {
  219. public:
  220. <span class="code-example-comment"> /// LimitStopwatch
  221. /// Constructor
  222. </span> LimitStopwatch(int nUnits = kUnitsCycles, uint32_t nLimit = 0, bool bStartImmediately = false);
  223. <span class="code-example-comment"> /// SetTimeLimit
  224. /// Sets the time limit and lets you start the stopwatch at the same time.
  225. </span> void SetTimeLimit(uint32_t nLimit, bool bStartImmediately = false);
  226. <span class="code-example-comment"> /// IsTimeUp
  227. /// Returns true if the limit has been reached. Highly efficient.
  228. </span> bool IsTimeUp();
  229. <span class="code-example-comment"> /// GetTimeRemaining
  230. /// More expensive than IsTimeUp, as it returns a value.
  231. </span> int64_t GetTimeRemaining();
  232. <span class="code-example-comment"> /// GetTimeRemainingFloat
  233. /// More expensive than IsTimeUp, as it returns a value.
  234. </span> float GetTimeRemainingFloat();
  235. };</pre>
  236. <hr>
  237. <p>&nbsp;</p>
  238. <p>&nbsp;</p>
  239. <p>&nbsp;</p>
  240. <p>&nbsp;</p>
  241. <p>&nbsp;</p>
  242. <p>&nbsp;</p>
  243. <p>&nbsp;</p>
  244. <p>&nbsp;</p>
  245. <p>&nbsp;</p>
  246. <p>&nbsp;</p>
  247. <p>&nbsp;</p>
  248. <p>&nbsp;</p>
  249. <p>&nbsp;</p>
  250. <p> </p>
  251. </body></html>