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-2017 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///
40{
41public:
42 /// collected statistics
43 ///
45 {
46 std::chrono::duration<double, std::milli> duration;
47 unsigned repeats;
48
50
51 statistics(std::chrono::duration<double, std::milli> d, unsigned r)
52 : duration(d), repeats(r)
53 {}
54 };
55
62
63 /// test name to duration map
64 ///
65 typedef std::map<std::string, statistics > duration_map_type;
66
67public:
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 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;
202
203protected:
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
Utility class to collect performance measurements and statistics.
Definition bmtimer.h:40
std::chrono::time_point< std::chrono::steady_clock > start_
Definition bmtimer.h:205
std::string name_
Definition bmtimer.h:204
std::map< std::string, statistics > duration_map_type
test name to duration map
Definition bmtimer.h:65
static void print_duration_map(const duration_map_type &dmap, format fmt=ct_time)
Definition bmtimer.h:127
duration_map_type * dmap_
Definition bmtimer.h:208
void add_repeats(unsigned inc)
Definition bmtimer.h:121
void stop(bool silent=false)
Definition bmtimer.h:93
chrono_taker(const chrono_taker &)=delete
unsigned repeats_
Definition bmtimer.h:207
chrono_taker(const std::string name, unsigned repeats=1, duration_map_type *dmap=0)
Definition bmtimer.h:68
chrono_taker & operator=(const chrono_taker)=delete
std::chrono::time_point< std::chrono::steady_clock > finish_
Definition bmtimer.h:206
Definition bm.h:77
collected statistics
Definition bmtimer.h:45
std::chrono::duration< double, std::milli > duration
Definition bmtimer.h:46
statistics(std::chrono::duration< double, std::milli > d, unsigned r)
Definition bmtimer.h:51
const unsigned repeats