-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTimer.cpp
More file actions
186 lines (173 loc) · 6.31 KB
/
Timer.cpp
File metadata and controls
186 lines (173 loc) · 6.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/*
* Class Timer (c++ version).
* Karim Sultan, ported September 8 2022 from Python.
* A high resolution timer (stopwatch) for performance timing.
*
* Why this was ported: I find myself doing a lot of C++
* for quick tasks over Python; and a high resolution timer
* is very handy.
*
* From Python source:
* +++++++++++++++++++
* Timer class - acts as performance stopwatch.
* Use as follows within code:
* *
* Usage:
* from timer import Timer
* Timer timer;
* timer.start()
* ... do measurable stuff ...
* timer.stop()
* std::cout << "Time taken: " << timer.elapsed() << std::endl;
*
* PYTHON HISTORY:
* KSU 201010 Made field attributes private. Made elapsed() stop
* the timer if it is still running. Added sanity checks.
* Added test cases. Added some robustness.
* KSU 201025 Added units to elapsed(). Updated test cases. Fixed a previously
* uknown and rather insidious bug in timer.stop() which didn't check
* if it had already been stopped, and would update elapsed time errantly.
* KSU 201028 Added support for nanoseconds and microseconds in timer.elapsed().
* Updated unit test for elapsed time accordingly.
* NOTE: The µ utf-8 character in windows is ALT-230.
* KSU 201103 Two steps forward one step back... units function broke peek().
* Unit tests caught error. Fixed.
*
* A note on timers...
* Timers are OS dependent. This will not work on UNIX.
* The OS is responsible for setting up a high resolution timer that is stable.
* The timer frequency may vary. The OS measures passage of time in ticks. The
* frequency provides the number of ticks per second. Dividing the high resolution
* counter (ticks) by the number of ticks per second will give you the number of
* seconds. It is possible to take a measurement at the nanosecond level, but
* drift due to the execution time of the start() and stop() method become noticeable.
* The windows API routines QueryPerformanceCounter and QueryPerformanceFrequency
* provide these values. This Timer class queries a start and stop time and converts
* elapsed time to a unit (ns, µs, ms, s, m, h, d) with minimal code.
* The peek method lets you view elapsed time without stopping the timer first.
* The elapsed method requires you stop the timer prior or it returns 0.
*/
#include "Timer.h"
#include <iostream>
#include <string>
#include <time.h>
#include <stdlib.h>
#include <Windows.h>
/// <summary>
/// Constructor resets key members.
/// </summary>
gamzia::Timer::Timer()
{
isRunning = false;
timeStart.QuadPart = 0;
timeStop.QuadPart = 0;
frequency.QuadPart = 0;
timeElapsed.QuadPart = 0;
}
/// <summary>
/// Starts the timer
/// </summary>
void gamzia::Timer::start(void)
{
isRunning = true;
QueryPerformanceFrequency(&frequency);
QueryPerformanceCounter(&timeStart);
}
/// <summary>
/// Stops the timer
/// </summary>
void gamzia::Timer::stop(void)
{
QueryPerformanceCounter(&timeStop);
isRunning=false;
}
/// <summary>
/// Returns elapsed time in your choice of units.The timer
/// must be stopped first before calling this, or it returns 0.
/// Specifying a unit returns the elapsed time in that format.
/// Format specifiers(long, medium and short form are valid) :
/// ns - nano - nanoseconds
/// µs - micro - microseconds
/// ms - milli - milliseconds
/// s - sec - seconds
/// m - min - minutes
/// h - hrs - hours
/// d - days
/// </summary>
/// <param name="units">A format prefix</param>
/// <returns>The elapsed time in the specified units</returns>
double gamzia::Timer::elapsed(std::string units)
{
if (isRunning)
return (0);
timeElapsed.QuadPart = timeStop.QuadPart - timeStart.QuadPart;
// We have to divide the number of ticks by the number of ticks per second.
double delta;
delta = (double)timeElapsed.QuadPart;
delta = delta / frequency.QuadPart;
return(convertUnits(delta, units));
}
/// <summary>
/// Peeks at the current timer value.Timer does not need to be stopped,
/// but must have been started, or it returns 0.
/// Specifying a unit returns the elapsed time in that format.
/// Format specifiers(long, medium and short form are valid) :
/// ns - nano - nanoseconds
/// µs - micro - microseconds
/// ms - milli - milliseconds
/// s - sec - seconds
/// m - min - minutes
/// h - hrs - hours
/// d - days
/// </summary>
/// <param name="units">A format prefix</param>
/// <returns>The time elapsed *so far*</returns>
double gamzia::Timer::peek(std::string units)
{
if (isRunning)
{
LARGE_INTEGER interim;
QueryPerformanceCounter(&interim);
timeElapsed.QuadPart = interim.QuadPart - timeStart.QuadPart;
// Divide tick count by number of ticks per second
double delta;
delta = (double)timeElapsed.QuadPart;
delta = delta / frequency.QuadPart;
return (convertUnits(delta, units));
}
else return(0);
}
/// <summary>
/// Private method which does the heavy lifting to format to a unit.
/// Called by elapsed() and peek().
/// </summary>
/// <param name="delta">The elapsed time, in seconds (ie, ticks divided
/// by ticks per second)</param>
/// <param name="units">The unit prefix</param>
/// <returns>The converted seconds value</returns>
double gamzia::Timer::convertUnits(double delta, std::string units)
{
double nanoseconds = (double)delta * 1000 * 1000 * 1000;
double microseconds = (double)delta * 1000 * 1000;
double milliseconds = (double)delta * 1000;
double seconds = (double)delta;
double minutes = (double)delta / 60;
double hours = minutes / 60;
double days = hours / 24;
if (units == "ns" || units == "nano" || units == "nanoseconds")
return (nanoseconds);
else if (units == "µs" || units == "micro" || units == "microseconds")
return (microseconds);
else if (units == "ms" || units == "milli" || units == "milliseconds")
return (milliseconds);
else if (units == "s" || units == "sec" || units == "seconds")
return (seconds);
else if (units == "m" || units == "min" || units == "minutes")
return (minutes);
else if (units == "h" || units == "hrs" || units == "hours")
return (hours);
else if (units == "d" || units == "days")
return (days);
else
return(0);
}