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