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