Ardour  8.12
timing.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014-2016 Tim Mayberry <mojofunk@gmail.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #ifndef __libpbd_timing_h__
20 #define __libpbd_timing_h__
21 
22 #include <glib.h>
23 
24 #include <stdint.h>
25 
26 #include <cmath>
27 #include <limits>
28 #include <string>
29 #include <vector>
30 
31 #include "pbd/microseconds.h"
32 #include "pbd/libpbd_visibility.h"
33 
34 #ifdef COMPILER_MSVC
35 #undef min
36 #undef max
37 #endif
38 
39 namespace PBD {
40 
41 LIBPBD_API bool get_min_max_avg_total (const std::vector<microseconds_t>& values, microseconds_t& min, microseconds_t& max, microseconds_t& avg, microseconds_t& total);
42 
43 LIBPBD_API std::string timing_summary (const std::vector<microseconds_t>& values);
44 
67 {
68 public:
69 
70  Timing ()
71  : m_start_val(0)
72  , m_last_val(0)
73  { start ();}
74 
75  bool valid () const {
76  return (m_start_val != 0 && m_last_val != 0);
77  }
78 
79  void start () {
80  m_start_val = PBD::get_microseconds ();
81  m_last_val = 0;
82  }
83 
84  void update () {
85  m_last_val = PBD::get_microseconds ();
86  }
87  void update (microseconds_t interval) {
88  m_start_val = 0;
89  m_last_val = interval;
90  }
91 
92  void reset () {
93  m_start_val = m_last_val = 0;
94  }
95 
97  microseconds_t elapsed = 0;
98  update ();
99  if (valid()) {
100  elapsed = m_last_val - m_start_val;
101  m_start_val = m_last_val;
102  m_last_val = 0;
103  }
104  return elapsed;
105  }
106 
107  bool started() const { return m_start_val != 0; }
108 
111  return m_last_val - m_start_val;
112  }
113 
116  return elapsed () / 1000;
117  }
118 
119  microseconds_t start_time() const { return m_start_val; }
120  microseconds_t last_time() const { return m_last_val; }
121 
122  protected:
125 
126 };
127 
129 {
130 public:
132  {
133  /* override implicit Timing::start () */
134  reset ();
135  }
136 
137  void update ()
138  {
139  if (_queue_reset) {
140  reset ();
141  } else {
142  Timing::update ();
143 
144  /* On Windows, querying the performance counter can fail occasionally (-1).
145  * Also on some multi-core systems, timers are CPU specific and not
146  * synchronized. The query can also fail, which will
147  * result in a value of zero, which is essentially impossible.
148  */
149 
150  if (m_start_val <= 0 || m_last_val <= 0 || m_start_val > m_last_val) {
151  return;
152  }
153 
154  calc ();
155  }
156  }
157 
158  void queue_reset () {
159  _queue_reset = true;
160  }
161 
162  void reset ()
163  {
164  _queue_reset = 0;
165  Timing::reset ();
166  _min = std::numeric_limits<microseconds_t>::max();
167  _max = 0;
168  _cnt = 0;
169  _avg = 0.;
170  _vm = 0.;
171  _vs = 0.;
172  }
173 
174  bool valid () const {
175  return Timing::valid () && _cnt > 1;
176  }
177 
179  microseconds_t& max,
180  double& avg,
181  double& dev) const
182  {
183  if (_cnt < 2) {
184  return false;
185  }
186  min = _min;
187  max = _max;
188  avg = _avg / (double)_cnt;
189  dev = sqrt (_vs / ((double) _cnt - 1.0));
190  return true;
191  }
192 
193 private:
194  void calc ()
195  {
196  const microseconds_t diff = elapsed ();
197 
198  _avg += (double) diff;
199 
200  if (diff > _max) {
201  _max = diff;
202  }
203  if (diff < _min) {
204  _min = diff;
205  }
206 
207  if (_cnt == 0) {
208  _vm = (double) diff;
209  } else {
210  const double ela = (double) diff;
211  const double var_m1 = _vm;
212  _vm = _vm + (ela - _vm) / (1.0 + (double) _cnt);
213  _vs = _vs + (ela - _vm) * (ela - var_m1);
214  }
215  ++_cnt;
216  }
217 
221  double _avg;
222  double _vm;
223  double _vs;
225 };
226 
232 {
233  public:
234  TimerRAII (TimingStats& ts, bool dbg = false) : stats (ts) { stats.start(); }
235  ~TimerRAII() { stats.update(); }
237 };
238 
246 {
247  public:
248  WaitTimerRAII (TimingStats& ts) : stats (ts) { if (stats.started()) { stats.update(); } }
249  ~WaitTimerRAII() { stats.start(); }
251 };
252 
254 {
255 public:
256  TimingData () : m_reserve_size(256)
257  { reset (); }
258 
259  void start_timing () {
260  m_timing.start ();
261  }
262 
263  void add_elapsed () {
264  m_timing.update ();
265  if (m_timing.valid()) {
266  m_elapsed_values.push_back (m_timing.elapsed());
267  }
268  }
269 
270  void add_interval () {
271  microseconds_t interval = m_timing.get_interval ();
272  m_elapsed_values.push_back (interval);
273  }
274 
275  void reset () {
276  m_elapsed_values.clear ();
277  m_elapsed_values.reserve (m_reserve_size);
278  }
279 
280  std::string summary () const
281  { return timing_summary (m_elapsed_values); }
282 
284  microseconds_t& max,
285  microseconds_t& avg,
286  microseconds_t& total) const
287  { return PBD::get_min_max_avg_total (m_elapsed_values, min, max, avg, total); }
288 
289  void reserve (uint32_t reserve_size)
290  { m_reserve_size = reserve_size; reset (); }
291 
292  std::vector<microseconds_t>::size_type size () const
293  { return m_elapsed_values.size(); }
294 
295 private:
296 
298 
299  uint32_t m_reserve_size;
300 
301  std::vector<microseconds_t> m_elapsed_values;
302 };
303 
305 {
306 public:
308  : m_data(data)
309  {
310  m_data.start_timing ();
311  }
312 
314  {
315  m_data.add_elapsed ();
316  }
317 
318 private:
319 
321 
322 };
323 
324 } // namespace PBD
325 
326 #endif // __libpbd_timing_h__
~Timed()
Definition: timing.h:313
Timed(TimingData &data)
Definition: timing.h:307
TimingData & m_data
Definition: timing.h:320
TimerRAII(TimingStats &ts, bool dbg=false)
Definition: timing.h:234
TimingStats & stats
Definition: timing.h:236
Timing m_timing
Definition: timing.h:297
void start_timing()
Definition: timing.h:259
std::vector< microseconds_t >::size_type size() const
Definition: timing.h:292
void add_elapsed()
Definition: timing.h:263
uint32_t m_reserve_size
Definition: timing.h:299
void add_interval()
Definition: timing.h:270
bool get_min_max_avg_total(microseconds_t &min, microseconds_t &max, microseconds_t &avg, microseconds_t &total) const
Definition: timing.h:283
std::string summary() const
Definition: timing.h:280
void reset()
Definition: timing.h:275
std::vector< microseconds_t > m_elapsed_values
Definition: timing.h:301
void reserve(uint32_t reserve_size)
Definition: timing.h:289
microseconds_t _cnt
Definition: timing.h:218
microseconds_t _max
Definition: timing.h:220
void update()
Definition: timing.h:137
double _vm
Definition: timing.h:222
double _avg
Definition: timing.h:221
int _queue_reset
Definition: timing.h:224
bool get_stats(microseconds_t &min, microseconds_t &max, double &avg, double &dev) const
Definition: timing.h:178
bool valid() const
Definition: timing.h:174
microseconds_t _min
Definition: timing.h:219
void reset()
Definition: timing.h:162
void queue_reset()
Definition: timing.h:158
double _vs
Definition: timing.h:223
void calc()
Definition: timing.h:194
bool valid() const
Definition: timing.h:75
Timing()
Definition: timing.h:70
void update(microseconds_t interval)
Definition: timing.h:87
bool started() const
Definition: timing.h:107
void start()
Definition: timing.h:79
void update()
Definition: timing.h:84
microseconds_t elapsed() const
Definition: timing.h:110
microseconds_t start_time() const
Definition: timing.h:119
microseconds_t m_last_val
Definition: timing.h:124
void reset()
Definition: timing.h:92
microseconds_t m_start_val
Definition: timing.h:123
microseconds_t elapsed_msecs() const
Definition: timing.h:115
microseconds_t get_interval()
Definition: timing.h:96
microseconds_t last_time() const
Definition: timing.h:120
WaitTimerRAII(TimingStats &ts)
Definition: timing.h:248
TimingStats & stats
Definition: timing.h:250
#define LIBPBD_API
PBD::PropertyDescriptor< timepos_t > start
Definition: axis_view.h:42
bool get_min_max_avg_total(const std::vector< microseconds_t > &values, microseconds_t &min, microseconds_t &max, microseconds_t &avg, microseconds_t &total)
int64_t microseconds_t
Definition: microseconds.h:29
microseconds_t get_microseconds()
std::string timing_summary(const std::vector< microseconds_t > &values)