BitMagic-C++
bmtimer.h
Go to the documentation of this file.
1 #ifndef BMTIMER__H__INCLUDED__
2 #define BMTIMER__H__INCLUDED__
3 /*
4 Copyright(c) 2002-2017 Anatoliy Kuznetsov(anatoliy_kuznetsov at yahoo.com)
5 
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9 
10  http://www.apache.org/licenses/LICENSE-2.0
11 
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 
18 For more information please visit: http://bitmagic.io
19 */
20 
21 /*! \file bmtimer.h
22  \brief Timing utilities for benchmarking (internal)
23 */
24 
25 #include <iostream>
26 #include <iomanip>
27 #include <string>
28 #include <map>
29 #include <chrono>
30 
31 namespace bm
32 {
33 
34 
35 /// Utility class to collect performance measurements and statistics.
36 ///
37 /// @internal
38 ///
40 {
41 public:
42  /// collected statistics
43  ///
44  struct statistics
45  {
46  std::chrono::duration<double, std::milli> duration;
47  unsigned repeats;
48 
49  statistics() : duration(0), repeats(1) {}
50 
51  statistics(std::chrono::duration<double, std::milli> d, unsigned r)
52  : duration(d), repeats(r)
53  {}
54  };
55 
56  enum format
57  {
58  ct_time = 0,
61  };
62 
63  /// test name to duration map
64  ///
65  typedef std::map<std::string, statistics > duration_map_type;
66 
67 public:
68  chrono_taker(const std::string name,
69  unsigned repeats = 1,
70  duration_map_type* dmap = 0)
71  : name_(name),
73  dmap_(dmap),
74  is_stopped_(false)
75  {
76  start_ = std::chrono::steady_clock::now();
77  }
78 
80  {
81  try
82  {
83  if (!is_stopped_)
84  {
85  stop();
86  }
87  }
88  catch(...)
89  {}
90  }
91 
92 
93  void stop(bool silent=false)
94  {
95  finish_ = std::chrono::steady_clock::now();
96  auto diff = finish_ - start_;
97  if (dmap_)
98  {
99  statistics st(diff, repeats_);
100  duration_map_type::iterator it = dmap_->find(name_);
101  if (it == dmap_->end())
102  {
103  (*dmap_)[name_] = st;
104  }
105  else
106  {
107  it->second.repeats++;
108  it->second.duration += st.duration;
109  }
110  }
111  else // report the measurements
112  {
113  if (!silent)
114  {
115  auto ms = std::chrono::duration <double, std::milli> (diff).count();
116  print_duration(name_, ms);
117  }
118  }
119  is_stopped_ = true;
120  }
121 
122  void add_repeats(unsigned inc)
123  {
124  repeats_ += inc;
125  }
126 
127  template<typename DT>
128  static void print_duration(const std::string& name, DT ms)
129  {
130  if (ms > 1000)
131  {
132  double sec = ms / 1000;
133  if (sec > 60)
134  {
135  double min = sec / 60;
136  std::cout << name << "; " << std::setprecision(4) << min << " min" << std::endl;
137  }
138  else
139  std::cout << name << "; " << std::setprecision(4) << sec << " sec" << std::endl;
140  }
141  else
142  std::cout << name << "; " << ms << " ms" << std::endl;
143  }
144 
145 
146  static void print_duration_map(const duration_map_type& dmap, format fmt = ct_time)
147  {
148  duration_map_type::const_iterator it = dmap.begin();
149  duration_map_type::const_iterator it_end = dmap.end();
150 
151  for ( ;it != it_end; ++it)
152  {
153  const chrono_taker::statistics& st = it->second;
154  format f;
155  if (st.repeats <= 1)
156  f = ct_time;
157  else
158  f = fmt;
159 
160  switch (f)
161  {
162  case ct_time:
163  print_time:
164  {
165  auto ms = it->second.duration.count();
166  print_duration(it->first, ms);
167  }
168  break;
169  case ct_ops_per_sec:
170  {
171  unsigned iops = (unsigned)((double)st.repeats / (double)it->second.duration.count()) * 1000;
172  if (iops)
173  {
174  std::cout << it->first << "; " << iops << " ops/sec" << std::endl;
175  }
176  else
177  {
178  double ops = ((double)st.repeats / (double)it->second.duration.count()) * 1000;
179  std::cout << it->first << "; " << std::setprecision(4) << ops << " ops/sec" << std::endl;
180  }
181  }
182  break;
183  case ct_all:
184  {
185  if (st.repeats <= 1)
186  {
187  goto print_time;
188  }
189  unsigned iops = (unsigned)((double)st.repeats / (double)it->second.duration.count()) * 1000;
190  if (iops)
191  {
192  std::cout << it->first << "; " << iops << " ops/sec; "
193  << std::setprecision(4) << it->second.duration.count() << " ms" << std::endl;
194  }
195  else
196  {
197  double sec = double(it->second.duration.count()) / 1000;
198 
199  double ops = ((double)st.repeats / (double)it->second.duration.count()) * 1000;
200  std::cout << it->first << "; " << std::setprecision(4) << ops << " ops/sec; "
201  << std::setprecision(4) << sec << " sec." << std::endl;
202  }
203  }
204  break;
205 
206  default:
207  break;
208  }
209  } // for
210  }
211 
212 
213  chrono_taker(const chrono_taker&) = delete;
214  chrono_taker & operator=(const chrono_taker) = delete;
215 
216 protected:
217  std::string name_;
218  std::chrono::time_point<std::chrono::steady_clock> start_;
219  std::chrono::time_point<std::chrono::steady_clock> finish_;
220  unsigned repeats_;
221  duration_map_type* dmap_;
223 };
224 
225 
226 } // namespace
227 
228 #endif
Definition: bm.h:76
void stop(bool silent=false)
Definition: bmtimer.h:93
static void print_duration(const std::string &name, DT ms)
Definition: bmtimer.h:128
unsigned repeats_
Definition: bmtimer.h:220
chrono_taker(const std::string name, unsigned repeats=1, duration_map_type *dmap=0)
Definition: bmtimer.h:68
bool is_stopped_
Definition: bmtimer.h:222
chrono_taker & operator=(const chrono_taker)=delete
std::chrono::time_point< std::chrono::steady_clock > start_
Definition: bmtimer.h:218
std::map< std::string, statistics > duration_map_type
test name to duration map
Definition: bmtimer.h:65
duration_map_type * dmap_
Definition: bmtimer.h:221
static void print_duration_map(const duration_map_type &dmap, format fmt=ct_time)
Definition: bmtimer.h:146
std::chrono::time_point< std::chrono::steady_clock > finish_
Definition: bmtimer.h:219
collected statistics
Definition: bmtimer.h:44
std::string name_
Definition: bmtimer.h:217
Utility class to collect performance measurements and statistics.
Definition: bmtimer.h:39
void add_repeats(unsigned inc)
Definition: bmtimer.h:122
statistics(std::chrono::duration< double, std::milli > d, unsigned r)
Definition: bmtimer.h:51
std::chrono::duration< double, std::milli > duration
Definition: bmtimer.h:46