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() : 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),
72  repeats_(repeats),
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  std::cout << it->first << "; " << std::setprecision(4) << sec << " sec" << std::endl;
151  }
152  else
153  std::cout << it->first << "; " << it->second.duration.count() << " ms" << std::endl;
154  }
155  break;
156  case ct_ops_per_sec:
157  {
158  unsigned iops = (unsigned)((double)st.repeats / (double)it->second.duration.count()) * 1000;
159  if (iops)
160  {
161  std::cout << it->first << "; " << iops << " ops/sec" << std::endl;
162  }
163  else
164  {
165  double ops = ((double)st.repeats / (double)it->second.duration.count()) * 1000;
166  std::cout << it->first << "; " << std::setprecision(4) << ops << " ops/sec" << std::endl;
167  }
168  }
169  break;
170  case ct_all:
171  {
172  if (st.repeats <= 1)
173  {
174  goto print_time;
175  }
176  unsigned iops = (unsigned)((double)st.repeats / (double)it->second.duration.count()) * 1000;
177  if (iops)
178  {
179  std::cout << it->first << "; " << iops << " ops/sec; "
180  << std::setprecision(4) << it->second.duration.count() << " ms" << std::endl;
181  }
182  else
183  {
184  double sec = double(it->second.duration.count()) / 1000;
185 
186  double ops = ((double)st.repeats / (double)it->second.duration.count()) * 1000;
187  std::cout << it->first << "; " << std::setprecision(4) << ops << " ops/sec; "
188  << std::setprecision(4) << sec << " sec." << std::endl;
189  }
190  }
191  break;
192 
193  default:
194  break;
195  }
196  } // for
197  }
198 
199 
200  chrono_taker(const chrono_taker&) = delete;
201  chrono_taker & operator=(const chrono_taker) = delete;
202 
203 protected:
204  std::string name_;
205  std::chrono::time_point<std::chrono::steady_clock> start_;
206  std::chrono::time_point<std::chrono::steady_clock> finish_;
207  unsigned repeats_;
210 };
211 
212 
213 } // namespace
214 
215 #endif
bm::chrono_taker::finish_
std::chrono::time_point< std::chrono::steady_clock > finish_
Definition: bmtimer.h:206
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:205
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:204
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:208
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
bm
Definition: bm.h:76
bm::chrono_taker::repeats_
unsigned repeats_
Definition: bmtimer.h:207
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:209
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