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  std::cout << name_ << ": "
115  << std::chrono::duration <double, std::milli> (diff).count()
116  << std::endl;
117  }
118  is_stopped_ = true;
119  }
120 
121  void add_repeats(unsigned inc)
122  {
123  repeats_ += inc;
124  }
125 
126 
127  static void print_duration_map(const duration_map_type& dmap, format fmt = ct_time)
128  {
129  duration_map_type::const_iterator it = dmap.begin();
130  duration_map_type::const_iterator it_end = dmap.end();
131 
132  for ( ;it != it_end; ++it)
133  {
134  const chrono_taker::statistics& st = it->second;
135  format f;
136  if (st.repeats <= 1)
137  f = ct_time;
138  else
139  f = fmt;
140 
141  switch (f)
142  {
143  case ct_time:
144  print_time:
145  {
146  auto ms = it->second.duration.count();
147  if (ms > 1000)
148  {
149  double sec = ms / 1000;
150  if (sec > 60)
151  {
152  double min = sec / 60;
153  std::cout << it->first << "; " << std::setprecision(4) << min << " min" << std::endl;
154  }
155  else
156  std::cout << it->first << "; " << std::setprecision(4) << sec << " sec" << std::endl;
157  }
158  else
159  std::cout << it->first << "; " << it->second.duration.count() << " ms" << std::endl;
160  }
161  break;
162  case ct_ops_per_sec:
163  {
164  unsigned iops = (unsigned)((double)st.repeats / (double)it->second.duration.count()) * 1000;
165  if (iops)
166  {
167  std::cout << it->first << "; " << iops << " ops/sec" << std::endl;
168  }
169  else
170  {
171  double ops = ((double)st.repeats / (double)it->second.duration.count()) * 1000;
172  std::cout << it->first << "; " << std::setprecision(4) << ops << " ops/sec" << std::endl;
173  }
174  }
175  break;
176  case ct_all:
177  {
178  if (st.repeats <= 1)
179  {
180  goto print_time;
181  }
182  unsigned iops = (unsigned)((double)st.repeats / (double)it->second.duration.count()) * 1000;
183  if (iops)
184  {
185  std::cout << it->first << "; " << iops << " ops/sec; "
186  << std::setprecision(4) << it->second.duration.count() << " ms" << std::endl;
187  }
188  else
189  {
190  double sec = double(it->second.duration.count()) / 1000;
191 
192  double ops = ((double)st.repeats / (double)it->second.duration.count()) * 1000;
193  std::cout << it->first << "; " << std::setprecision(4) << ops << " ops/sec; "
194  << std::setprecision(4) << sec << " sec." << std::endl;
195  }
196  }
197  break;
198 
199  default:
200  break;
201  }
202  } // for
203  }
204 
205 
206  chrono_taker(const chrono_taker&) = delete;
207  chrono_taker & operator=(const chrono_taker) = delete;
208 
209 protected:
210  std::string name_;
211  std::chrono::time_point<std::chrono::steady_clock> start_;
212  std::chrono::time_point<std::chrono::steady_clock> finish_;
213  unsigned repeats_;
216 };
217 
218 
219 } // namespace
220 
221 #endif
bm::chrono_taker::finish_
std::chrono::time_point< std::chrono::steady_clock > finish_
Definition: bmtimer.h:212
bm::chrono_taker
Utility class to collect performance measurements and statistics.
Definition: bmtimer.h:39
bm::chrono_taker::format
format
Definition: bmtimer.h:56
bm::chrono_taker::start_
std::chrono::time_point< std::chrono::steady_clock > start_
Definition: bmtimer.h:211
bm::chrono_taker::statistics::statistics
statistics()
Definition: bmtimer.h:49
bm::chrono_taker::chrono_taker
chrono_taker(const std::string name, unsigned repeats=1, duration_map_type *dmap=0)
Definition: bmtimer.h:68
bm::chrono_taker::name_
std::string name_
Definition: bmtimer.h:210
bm::chrono_taker::ct_time
@ ct_time
Definition: bmtimer.h:58
bm::chrono_taker::statistics::statistics
statistics(std::chrono::duration< double, std::milli > d, unsigned r)
Definition: bmtimer.h:51
bm::chrono_taker::ct_ops_per_sec
@ ct_ops_per_sec
Definition: bmtimer.h:59
bm::chrono_taker::ct_all
@ ct_all
Definition: bmtimer.h:60
bm::chrono_taker::~chrono_taker
~chrono_taker()
Definition: bmtimer.h:79
bm::chrono_taker::dmap_
duration_map_type * dmap_
Definition: bmtimer.h:214
bm::chrono_taker::duration_map_type
std::map< std::string, statistics > duration_map_type
test name to duration map
Definition: bmtimer.h:65
bm::chrono_taker::operator=
chrono_taker & operator=(const chrono_taker)=delete
bm::chrono_taker::statistics::repeats
unsigned repeats
Definition: bmtimer.h:47
bm::chrono_taker::print_duration_map
static void print_duration_map(const duration_map_type &dmap, format fmt=ct_time)
Definition: bmtimer.h:127
repeats
const unsigned repeats
Definition: xsample06.cpp:281
bm
Definition: bm.h:76
bm::chrono_taker::repeats_
unsigned repeats_
Definition: bmtimer.h:213
bm::chrono_taker::add_repeats
void add_repeats(unsigned inc)
Definition: bmtimer.h:121
bm::chrono_taker::statistics
collected statistics
Definition: bmtimer.h:44
bm::chrono_taker::is_stopped_
bool is_stopped_
Definition: bmtimer.h:215
bm::chrono_taker::stop
void stop(bool silent=false)
Definition: bmtimer.h:93
bm::chrono_taker::statistics::duration
std::chrono::duration< double, std::milli > duration
Definition: bmtimer.h:46