2 Copyright (C) 2014 Tim Mayberry
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.
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.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #ifndef __libpbd_timing_h__
21 #define __libpbd_timing_h__
32 #include "pbd/libpbd_visibility.h"
41 LIBPBD_API bool get_min_max_avg_total (const std::vector<uint64_t>& values, uint64_t& min, uint64_t& max, uint64_t& avg, uint64_t& total);
43 LIBPBD_API std::string timing_summary (const std::vector<uint64_t>& values);
46 * This class allows collecting timing data using two different
47 * techniques. The first is using start() and update() and then
48 * calling elapsed() to get the elapsed time. This is useful when
49 * you want to measure the elapsed time between two different
50 * execution points. e.g
55 * cerr << "do_stuff took: "
59 * The other is timing intervals using start() and calling
60 * get_interval() periodically to measure the time intervals
61 * between the same execution point. The difference is necessary
62 * to get the most accurate timing information when timing
63 * intervals but I didn't feel it necessary to have two separate
66 class LIBPBD_API Timing
76 return (m_start_val != 0 && m_last_val != 0);
80 m_start_val = g_get_monotonic_time ();
85 m_last_val = g_get_monotonic_time ();
89 m_start_val = m_last_val = 0;
92 uint64_t get_interval () {
96 elapsed = m_last_val - m_start_val;
97 m_start_val = m_last_val;
103 /// @return Elapsed time in microseconds
104 uint64_t elapsed () const {
105 return m_last_val - m_start_val;
108 /// @return Elapsed time in milliseconds
109 uint64_t elapsed_msecs () const {
110 return elapsed () / 1000;
115 uint64_t m_start_val;
120 class LIBPBD_API TimingStats : public Timing
125 /* override implicit Timing::start () */
138 _min = std::numeric_limits<uint64_t>::max();
146 bool valid () const {
147 return Timing::valid () && _cnt > 1;
150 bool get_stats (uint64_t& min,
160 avg = _avg / (double)_cnt;
161 dev = sqrt (_vs / (_cnt - 1.0));
168 const uint64_t diff = elapsed ();
182 const double ela = diff;
183 const double var_m1 = _vm;
184 _vm = _vm + (ela - _vm) / (1.0 + _cnt);
185 _vs = _vs + (ela - _vm) * (ela - var_m1);
198 class LIBPBD_API TimingData
201 TimingData () : m_reserve_size(256)
204 void start_timing () {
208 void add_elapsed () {
210 if (m_timing.valid()) {
211 m_elapsed_values.push_back (m_timing.elapsed());
215 void add_interval () {
216 uint64_t interval = m_timing.get_interval ();
217 m_elapsed_values.push_back (interval);
221 m_elapsed_values.clear ();
222 m_elapsed_values.reserve (m_reserve_size);
225 std::string summary () const
226 { return timing_summary (m_elapsed_values); }
228 bool get_min_max_avg_total (uint64_t& min,
231 uint64_t& total) const
232 { return PBD::get_min_max_avg_total (m_elapsed_values, min, max, avg, total); }
234 void reserve (uint32_t reserve_size)
235 { m_reserve_size = reserve_size; reset (); }
237 uint32_t size () const
238 { return m_elapsed_values.size(); }
244 uint32_t m_reserve_size;
246 std::vector<uint64_t> m_elapsed_values;
249 class LIBPBD_API Timed
252 Timed (TimingData& data)
255 m_data.start_timing ();
260 m_data.add_elapsed ();
271 #endif // __libpbd_timing_h__