HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
timer.h
Go to the documentation of this file.
1 // Copyright 2008-present Contributors to the OpenImageIO project.
2 // SPDX-License-Identifier: BSD-3-Clause
3 // https://github.com/OpenImageIO/oiio
4 
5 
6 /// @file timer.h
7 /// @brief Simple timer class.
8 
9 
10 #pragma once
11 
12 #include <ctime>
13 #include <functional>
14 #include <iostream>
15 
16 #include <OpenImageIO/export.h>
19 #include <OpenImageIO/platform.h>
20 #include <OpenImageIO/span.h>
21 #include <OpenImageIO/strutil.h>
22 
23 #ifdef _WIN32
24 //# include <windows.h> // Already done by platform.h
25 #elif defined(__APPLE__)
26 # include <mach/mach_time.h>
27 #else
28 # include <sys/time.h>
29 #endif
30 
31 
33 
34 /// Simple timer class.
35 ///
36 /// This class allows you to time things, for runtime statistics and the
37 /// like. The simplest usage pattern is illustrated by the following
38 /// example:
39 ///
40 /// \code
41 /// Timer mytimer; // automatically starts upon construction
42 /// ...do stuff
43 /// float t = mytimer(); // seconds elapsed since start
44 ///
45 /// Timer another (false); // false means don't start ticking yet
46 /// another.start (); // start ticking now
47 /// another.stop (); // stop ticking
48 /// another.start (); // start again where we left off
49 /// another.stop ();
50 /// another.reset (); // reset to zero time again
51 /// \endcode
52 ///
53 /// These are not very high-resolution timers. A Timer begin/end pair
54 /// takes somewhere in the neighborhood of 0.1 - 0.3 us (microseconds),
55 /// and can vary by OS. This means that (a) it's not useful for timing
56 /// individual events near or below that resolution (things that would
57 /// take only tens or hundreds of processor cycles, for example), and
58 /// (b) calling it millions of times could make your program appreciably
59 /// more expensive due to the timers themselves.
60 ///
62 public:
63  typedef long long ticks_t;
64  enum StartNowVal { DontStartNow, StartNow };
65  enum PrintDtrVal { DontPrintDtr, PrintDtr };
66 
67  /// Constructor -- reset at zero, and start timing unless optional
68  /// 'startnow' argument is false.
69  Timer(StartNowVal startnow = StartNow, PrintDtrVal printdtr = DontPrintDtr,
70  const char* name = NULL)
71  : m_ticking(false)
72  , m_printdtr(printdtr == PrintDtr)
73  , m_starttime(0)
74  , m_elapsed_ticks(0)
75  , m_name(name)
76  {
77  if (startnow == StartNow)
78  start();
79  }
80 
81  /// Constructor -- reset at zero, and start timing unless optional
82  /// 'startnow' argument is false.
83  Timer(bool startnow)
84  : m_ticking(false)
85  , m_printdtr(DontPrintDtr)
86  , m_starttime(0)
87  , m_elapsed_ticks(0)
88  , m_name(NULL)
89  {
90  if (startnow)
91  start();
92  }
93 
94  /// Destructor.
96  {
97  if (m_printdtr == PrintDtr)
98  Strutil::printf("Timer %s: %gs\n", (m_name ? m_name : ""),
99  seconds(ticks()));
100  }
101 
102  /// Start (or restart) ticking, if we are not currently.
103  void start()
104  {
105  if (!m_ticking) {
106  m_starttime = now();
107  m_ticking = true;
108  }
109  }
110 
111  /// Stop ticking, return the total amount of time that has ticked
112  /// (both this round as well as previous laps). Current ticks will
113  /// be added to previous elapsed time.
114  double stop()
115  {
116  if (m_ticking) {
117  ticks_t n = now();
118  m_elapsed_ticks += tickdiff(m_starttime, n);
119  m_ticking = false;
120  }
121  return seconds(m_elapsed_ticks);
122  }
123 
124  /// Reset at zero and stop ticking.
125  ///
126  void reset(void)
127  {
128  m_elapsed_ticks = 0;
129  m_ticking = false;
130  }
131 
132  /// Return just the ticks of the current lap (since the last call to
133  /// start() or lap()), add that to the previous elapsed time, reset
134  /// current start time to now, keep the timer going (if it was).
136  {
137  ticks_t n = now();
138  ticks_t r = m_ticking ? tickdiff(m_starttime, n) : ticks_t(0);
139  m_elapsed_ticks += r;
140  m_starttime = n;
141  m_ticking = true;
142  return r;
143  }
144 
145  /// Return just the time of the current lap (since the last call to
146  /// start() or lap()), add that to the previous elapsed time, reset
147  /// current start time to now, keep the timer going (if it was).
148  double lap() { return seconds(lap_ticks()); }
149 
150  /// Total number of elapsed ticks so far, including both the currently-
151  /// ticking clock as well as any previously elapsed time.
152  ticks_t ticks() const { return ticks_since_start() + m_elapsed_ticks; }
153 
154  /// Operator () returns the elapsed time so far, in seconds, including
155  /// both the currently-ticking clock as well as any previously elapsed
156  /// time.
157  double operator()(void) const { return seconds(ticks()); }
158 
159  /// Return just the ticks since we called start(), not any elapsed
160  /// time in previous start-stop segments.
162  {
163  return m_ticking ? tickdiff(m_starttime, now()) : ticks_t(0);
164  }
165 
166  /// Return just the time since we called start(), not any elapsed
167  /// time in previous start-stop segments.
168  double time_since_start(void) const { return seconds(ticks_since_start()); }
169 
170  /// Convert number of ticks to seconds.
171  static double seconds(ticks_t ticks) { return ticks * seconds_per_tick; }
172 
173  /// Is the timer currently ticking?
174  bool ticking() const { return m_ticking; }
175 
176  /// Force an offset to the total, in ticks. This value may be negative to
177  /// subtract from the total. To avoid disrupting the timer in progress,
178  /// this is added to the total elapsed time but not to the current lap, so
179  /// it will be reflected in ticks() or seconds(), but will NOT be
180  /// reflected in ticks_since_start() or time_since_start().
181  void add_ticks(ticks_t delta) { m_elapsed_ticks += delta; }
182 
183  /// Force an offset to the total, in seconds. This value may be negative
184  /// to subtract from the total. To avoid disrupting the timer in progress,
185  /// this is added to the total elapsed time but not to the current lap, so
186  /// it will be reflected in ticks() or seconds(), but will NOT be
187  /// reflected in ticks_since_start() or time_since_start().
188  void add_seconds(double t) { add_ticks(ticks_t(t * ticks_per_second)); }
189 
190 private:
191  bool m_ticking; ///< Are we currently ticking?
192  bool m_printdtr; ///< Print upon destruction?
193  ticks_t m_starttime; ///< Time since last call to start()
194  ticks_t m_elapsed_ticks; ///< Time elapsed BEFORE the current start().
195  const char* m_name; ///< Timer name
196 
197  /// Platform-dependent grab of current time, expressed as ticks_t.
198  ///
199  ticks_t now(void) const
200  {
201 #ifdef _WIN32
202  LARGE_INTEGER n;
203  QueryPerformanceCounter(&n); // From MSDN web site
204  return n.QuadPart;
205 #elif defined(__APPLE__)
206  return mach_absolute_time();
207 #else
208  struct timeval t;
209  gettimeofday(&t, NULL);
210  return (long long)t.tv_sec * 1000000ll + t.tv_usec;
211 #endif
212  }
213 
214  /// Difference between two times, expressed in (platform-dependent)
215  /// ticks.
216  ticks_t tickdiff(ticks_t then, ticks_t now) const
217  {
218  return (now > then) ? now - then : then - now;
219  }
220 
221  /// Difference between two times, expressed in seconds.
222  double diff(ticks_t then, ticks_t now) const
223  {
224  return seconds(tickdiff(then, now));
225  }
226 
227  static double seconds_per_tick;
228  static ticks_t ticks_per_second;
229  friend class TimerSetupOnce;
230 };
231 
232 
233 
234 /// Helper class that starts and stops a timer when the ScopedTimer goes
235 /// in and out of scope.
236 class ScopedTimer {
237 public:
238  /// Given a reference to a timer, start it when this constructor
239  /// occurs.
241  : m_timer(t)
242  {
243  start();
244  }
245 
246  /// Stop the timer from ticking when this object is destroyed (i.e.
247  /// it leaves scope).
249 
250  /// Explicit start of the timer.
251  ///
252  void start() { m_timer.start(); }
253 
254  /// Explicit stop of the timer.
255  ///
256  void stop() { m_timer.stop(); }
257 
258  /// Explicit reset of the timer.
259  ///
260  void reset() { m_timer.reset(); }
261 
262 private:
263  Timer& m_timer;
264 };
265 
266 
267 
269 
270 
271 // DEPRECATED(1.8): for back compatibility with old inclusion of some
272 // functions that used to be here but are now in benchmark.h, include it.
273 #include <OpenImageIO/benchmark.h>
PrintDtrVal
Definition: timer.h:65
void printf(const char *fmt, const Args &...args)
Definition: strutil.h:171
Definition: timer.h:61
double stop()
Definition: timer.h:114
Timer(StartNowVal startnow=StartNow, PrintDtrVal printdtr=DontPrintDtr, const char *name=NULL)
Definition: timer.h:69
GLuint start
Definition: glcorearb.h:475
ScopedTimer(Timer &t)
Definition: timer.h:240
long long ticks_t
Definition: timer.h:63
void start()
Start (or restart) ticking, if we are not currently.
Definition: timer.h:103
ticks_t lap_ticks()
Definition: timer.h:135
GLuint const GLchar * name
Definition: glcorearb.h:786
String-related utilities, all in namespace Strutil.
GLdouble GLdouble t
Definition: glew.h:1403
#define OIIO_UTIL_API
Definition: export.h:71
Timer(bool startnow)
Definition: timer.h:83
**If you just want to fire and then
Definition: thread.h:609
bool ticking() const
Is the timer currently ticking?
Definition: timer.h:174
~ScopedTimer()
Definition: timer.h:248
void add_ticks(ticks_t delta)
Definition: timer.h:181
double time_since_start(void) const
Definition: timer.h:168
double lap()
Definition: timer.h:148
ticks_t ticks() const
Definition: timer.h:152
void start()
Definition: timer.h:252
void reset(void)
Definition: timer.h:126
GLdouble n
Definition: glcorearb.h:2008
double operator()(void) const
Definition: timer.h:157
void reset()
Definition: timer.h:260
void stop()
Definition: timer.h:256
StartNowVal
Definition: timer.h:64
#define OIIO_NAMESPACE_END
Definition: oiioversion.h:94
GLfloat seconds
Definition: wglew.h:950
void add_seconds(double t)
Definition: timer.h:188
GLboolean r
Definition: glcorearb.h:1222
ticks_t ticks_since_start(void) const
Definition: timer.h:161
~Timer()
Destructor.
Definition: timer.h:95
static double seconds(ticks_t ticks)
Convert number of ticks to seconds.
Definition: timer.h:171
#define OIIO_NAMESPACE_BEGIN
Definition: oiioversion.h:93