SUNphi  1.0
Timer.hpp
Go to the documentation of this file.
1 #ifndef _TIMER_HPP
2 #define _TIMER_HPP
3 
4 /// \file Timer.hpp
5 ///
6 /// \brief Provides a timer which can be split
7 ///
8 
9 #ifdef HAVE_CONFIG_H
10  #include "config.hpp"
11 #endif
12 
13 #include <chrono>
14 
15 #include <containers/Map.hpp>
16 #include <debug/MinimalCrash.hpp>
17 #include <metaprogramming/TypeTraits.hpp>
18 #include <metaprogramming/UniversalReferences.hpp>
19 
20 namespace SUNphi
21 {
22  /// Machine clock type
23  using Clock=
24  std::chrono::steady_clock;
25 
26  /// Instant type, defining a moment in time
27  using Instant=
28  std::chrono::time_point<Clock>;
29 
30  /// Difference of time between two moments
31  using Duration=
32  decltype(Instant{}-Instant{});
33 
34  /// Get current time
35  inline Instant takeTime()
36  {
37  return
38  Clock::now();
39  }
40 
41  /// Splittable stopwatch
42  ///
43  /// If the stopwatch is created with \c isStoppable set to true, it
44  /// cannot be stopped and is automatically started
45  class Timer
46  {
47  /// Number of intervals measured
48  int nMeasures;
49 
50  /// Mark if the stopwatch is started
52 
53  /// Last moment the stopwatch was started
55 
56  /// Last moment the stopwatch was stopped
58 
59  /// Cumulative time for which the timer has been let running
61 
62  /// Father of current timer
64 
65  /// Number of children measuring
67 
68  /// Children
70 
71  /// Determine whether it was explicitly started (or from a children)
73 
74  /// Started mode: was it started by a children or explicityly?
75  enum Started{IMPLICITLY,EXPLICITLY};
76 
77  /// Common start
78  void innerStart(const bool implExpl)
79  {
80  // Check that the timer was not started already
81  if(isStarted())
82  MINIMAL_CRASH("Trying to start the already started stopwatch: %s",name);
83 
84  // Mark the timer as started
86  true;
87 
88  /// Store whether the stopwatch was explitly or implicitly started
90  (implExpl==EXPLICITLY);
91 
92  // Increments the number of intervals measured
93  nMeasures++;
94 
95  // Take current time
96  lastMomentStarted=
97  takeTime();
98  }
99 
100  /// Starts through a children
102  {
103  if(not isStarted())
104  innerStart(IMPLICITLY);
105 
106  nStartedChildren++;
107  }
108 
109  public:
110 
111  /// Gets reference to the mapped sub timer
112  Timer& operator[](const char* subName)
113  {
114  /// Finds the sub timer
115  auto ref=
116  children.find(subName);
117 
118  // Insert if not found
119  if(ref==children.end())
120  ref=
121  children.try_emplace(subName,subName,this).first;
122 
123  return
124  ref->second;
125  }
126 
127  /// Checks if has children
128  bool hasChildren()
129  const
130  {
131  return
132  children.size();
133  }
134 
135  /// Checks if has running children
137  const
138  {
139  return
140  nStartedChildren!=0;
141  }
142 
143  /// Gets a reference to the father
144  const Timer& father()
145  const
146  {
147  return
148  *_father;
149  }
150 
152 
153  /// Used to mark that there is no father
154  static constexpr Timer* NO_FATHER=
155  nullptr;
156 
157  /// Defines whether the timer can be stopped or not
158  enum{UNSTOPPABLE,STOPPABLE};
159 
160  /// Name of the timer
161  const char* name;
162 
163  /// Mark whether the stopwatch can be stopped
164  const bool isStoppable;
165 
166  /// Returns whether the timer is started
167  const bool& isStarted()
168  const
169  {
170  return
172  }
173 
174  /// Explicitly starts the stopwatch
175  void start()
176  {
177  innerStart(EXPLICITLY);
178  }
179 
180  /// Returns the last measured or the current one
182  const
183  {
184  if(isStarted())
185  return
186  takeTime()-lastMomentStarted;
187  else
188  return
189  lastMomentStopped-lastMomentStarted;
190  }
191 
192  /// Returns the total measured time, including current one if is running
194  const
195  {
196  if(isStarted())
197  return
198  _cumulativeMeasure+currentMeasure();
199  else
200  return
201  _cumulativeMeasure;
202  }
203 
204  /// Average measure
206  const
207  {
208  return
209  cumulativeMeasure()/nMeasures;
210  }
211 
212  /// Stop the stopwatch
213  void stop()
214  {
215  if(not isStarted())
216  MINIMAL_CRASH("Trying to stop the stopped stopwatch %s",name);
217 
218  if(not isStoppable)
219  MINIMAL_CRASH("Trying to stop the unstoppable stopwatch %s",name);
220 
221  if(hasRunningChildren())
222  MINIMAL_CRASH("Trying to stop stopwatch %s with %d running children",name,nStartedChildren);
223 
224  // Store the stopping time
225  lastMomentStopped=
226  takeTime();
227 
228  // Mark as stopped
230  false;
231 
232  // Increment the cumulative measure
233  _cumulativeMeasure+=
234  currentMeasure();
235  }
236 
237  /// Builds the stopwatch
238  Timer(const char* name, ///< Name of the timer
239  Timer* father=nullptr, ///< Father of current timer
240  const bool isStoppableFlag=STOPPABLE) ///< Flag determining if the stopwatch can be stopped
241  :
242  nMeasures(0),
243  isStartedFlag(false),
246  name(name),
247  isStoppable(isStoppableFlag)
248 
249  {
250  // Auto starts the stopwatch if it cannot be stopped
251  if(not isStoppable)
252  start();
253  }
254  };
255 
256  /// Convert duration into a units of measure
257  template <typename U, // Units
258  typename O=double> // Output type
259  double durationIn(const Duration& duration) ///< Input duration
260  {
261  return
262  std::chrono::duration<O,U>(duration).count();
263  }
264 
265  /// Convert duration into seconds
266  template <typename O=double> // Output type
267  double durationInSec(const Duration& duration) ///< Input duration
268  {
269  return
270  std::chrono::duration<O>(duration).count();
271  }
272 
273  extern Timer timings;
274 
275  /// Returns the duration of executing a function
276  template <typename F, // Function type
277  typename...Args> // Arguments type
278  auto durationOf(Duration& duration, ///< Variable where to store the duration
279  F&& f, ///< Function to execute
280  Args&&...args) ///< Arguments to call
281  {
282  /// Beginning instant
283  Instant start=
284  takeTime();
285 
286  /// Store the result
287  auto res=
288  f(forw<Args>(args)...);
289 
290  duration=
291  takeTime()-start;
292 
293  return
294  res;
295  }
296 
297  /// Returns the duration of executing a function
298  ///
299  /// Result of f() is discarded
300  template <typename F, // Function type
301  typename...Args> // Arguments type
302  Duration durationOf(F&& f, ///< Function to execute
303  Args&&...args) ///< Arguments to call
304  {
305  /// Result to be returned
306  Duration duration;
307 
308  duationOf(duration,forw<F>(f),forw<Args>(args)...);
309 
310  return
311  duration;
312  }
313 
314 }
315 
316 #endif
#define MINIMAL_CRASH(...)
Initialize the minimal crasher.
bool hasRunningChildren() const
Checks if has running children.
Definition: Timer.hpp:136
double durationIn(const Duration &duration)
Convert duration into a units of measure.
Definition: Timer.hpp:259
auto durationOf(Duration &duration, F &&f, Args &&...args)
Returns the duration of executing a function.
Definition: Timer.hpp:278
void minimalCrash(const char *path, const int line, const char *funcName, const char *format,...)
Definition: SUNphi.cpp:53
const bool & isStarted() const
Returns whether the timer is started.
Definition: Timer.hpp:167
Duration cumulativeMeasure() const
Returns the total measured time, including current one if is running.
Definition: Timer.hpp:193
Duration _cumulativeMeasure
Cumulative time for which the timer has been let running.
Definition: Timer.hpp:60
Instant lastMomentStarted
Last moment the stopwatch was started.
Definition: Timer.hpp:54
Started
Started mode: was it started by a children or explicityly?
Definition: Timer.hpp:75
Timer & operator[](const char *subName)
Gets reference to the mapped sub timer.
Definition: Timer.hpp:112
decltype(auto) father(Ts &&...ts)
Definition: Timer.hpp:151
Timer * _father
Father of current timer.
Definition: Timer.hpp:63
bool isStartedFlag
Mark if the stopwatch is started.
Definition: Timer.hpp:51
void innerStart(const bool implExpl)
Common start.
Definition: Timer.hpp:78
bool hasChildren() const
Checks if has children.
Definition: Timer.hpp:128
bool isExplicitlyStarted
Determine whether it was explicitly started (or from a children)
Definition: Timer.hpp:72
void start()
Explicitly starts the stopwatch.
Definition: Timer.hpp:175
Duration averageMeasure() const
Average measure.
Definition: Timer.hpp:205
const char * name
Name of the timer.
Definition: Timer.hpp:161
void childrenStarted()
Starts through a children.
Definition: Timer.hpp:101
Timer(const char *name, Timer *father=nullptr, const bool isStoppableFlag=STOPPABLE)
Builds the stopwatch.
Definition: Timer.hpp:238
const Timer & father() const
Gets a reference to the father.
Definition: Timer.hpp:144
const bool isStoppable
Mark whether the stopwatch can be stopped.
Definition: Timer.hpp:164
#define PROVIDE_ALSO_NON_CONST_METHOD(NAME)
Definition: TypeTraits.hpp:376
int nMeasures
Number of intervals measured.
Definition: Timer.hpp:48
double durationInSec(const Duration &duration)
Convert duration into seconds.
Definition: Timer.hpp:267
Timer timings("Total time", Timer::NO_FATHER, Timer::UNSTOPPABLE)
Global timings.
Instant takeTime()
Get current time.
Definition: Timer.hpp:35
Duration currentMeasure() const
Returns the last measured or the current one.
Definition: Timer.hpp:181
void stop()
Stop the stopwatch.
Definition: Timer.hpp:213