TBTK
Need a break? Support the development by playing Polarity Puzzles
Timer.h
Go to the documentation of this file.
1 /* Copyright 2016 Kristofer Björnson
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
23 #ifndef COM_DAFER45_TBTK_TIMER
24 #define COM_DAFER45_TBTK_TIMER
25 
26 #include "TBTK/Streams.h"
27 #include "TBTK/TBTKMacros.h"
28 
29 #include <chrono>
30 #include <iomanip>
31 #include <vector>
32 
33 namespace TBTK{
34 
75 class Timer{
76 public:
81  static void tick(std::string tag = "");
82 
85  static void tock();
86 
95  static unsigned int createAccumulator(const std::string &tag = "");
96 
100  static void tick(unsigned int id);
101 
105  static void tock(unsigned int id);
106 
110  static void resetAccumulator(unsigned int id);
111 
113  static void resetAccumulators();
114 
116  static void printAccumulators();
117 private:
119  static std::vector<std::chrono::time_point<std::chrono::high_resolution_clock>> timestamps;
120 
122  static std::vector<std::string> tags;
123 
125  static std::vector<std::chrono::time_point<std::chrono::high_resolution_clock>> accumulatorTimestamps;
126 
128  static std::vector<std::string> accumulatorTags;
129 
131  static std::vector<long> accumulators;
132 };
133 
134 inline void Timer::tick(std::string tag){
135  timestamps.push_back(std::chrono::high_resolution_clock::now());
136  tags.push_back(tag);
137 }
138 
139 inline void Timer::tock(){
140  std::chrono::time_point<std::chrono::high_resolution_clock> stop = std::chrono::high_resolution_clock::now();
141  if(timestamps.size() > 0){
142  std::chrono::time_point<std::chrono::high_resolution_clock> start = timestamps.back();
143  timestamps.pop_back();
144  std::string tag = tags.back();
145  tags.pop_back();
146 
147  int hours = (std::chrono::duration_cast<std::chrono::hours>(stop - start).count());
148  int minutes = (std::chrono::duration_cast<std::chrono::minutes>(stop - start).count())%60;
149  int seconds = (std::chrono::duration_cast<std::chrono::seconds>(stop - start).count())%60;
150  int milliseconds = (std::chrono::duration_cast<std::chrono::milliseconds>(stop - start).count())%1000;
151  int microseconds = (std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count())%1000;
152  int nanoseconds = (std::chrono::duration_cast<std::chrono::nanoseconds>(stop - start).count())%1000;
153 
154  Streams::out << "(" << timestamps.size() << ") ";
155  if(hours > 0)
156  Streams::out << hours << "h ";
157  if(hours > 0 || minutes > 0)
158  Streams::out << minutes << "m ";
159  if(hours > 0 || minutes > 0 || seconds > 0)
160  Streams::out << seconds << "s ";
161  if(hours > 0 || minutes > 0 || seconds > 0 || milliseconds > 0)
162  Streams::out << milliseconds << "ms ";
163  if(hours > 0 || minutes > 0 || seconds > 0 || milliseconds > 0 || microseconds > 0)
164  Streams::out << microseconds << "us ";
165  if(hours > 0 || minutes > 0 || seconds > 0 || milliseconds > 0 || microseconds > 0 || nanoseconds > 0)
166  Streams::out << nanoseconds << "ns ";
167  Streams::out << "\t" << tag << "\n";
168  }
169  else{
170  Streams::out << "Error in Time::tock(): No corresponding tick call made.\n";
171  }
172 }
173 
174 inline unsigned int Timer::createAccumulator(const std::string &tag){
175  accumulatorTimestamps.push_back(
176  std::chrono::high_resolution_clock::now()
177  );
178  accumulatorTags.push_back(tag);
179  accumulators.push_back(0);
180 
181  return accumulators.size() - 1;
182 }
183 
184 inline void Timer::tick(unsigned int id){
185  TBTKAssert(
186  id < accumulators.size(),
187  "Timer::tick()",
188  "'id' is out of bounds.",
189  "Ensure that the id corresponds to a value returned by a"
190  << " corresponding call to Timer::createAccumulator()."
191  );
192  accumulatorTimestamps[id] = std::chrono::high_resolution_clock::now();
193 }
194 
195 inline void Timer::tock(unsigned int id){
196  TBTKAssert(
197  id < accumulators.size(),
198  "Timer::tock()",
199  "'id' is out of bounds.",
200  "Ensure that the id corresponds to a value returned by a"
201  << " corresponding call to Timer::createAccumulator()."
202  );
203  std::chrono::time_point<std::chrono::high_resolution_clock> stop
204  = std::chrono::high_resolution_clock::now();
205  std::chrono::time_point<std::chrono::high_resolution_clock> start
206  = accumulatorTimestamps[id];
207 
208  accumulators[id]
209  += std::chrono::duration_cast<std::chrono::nanoseconds>(
210  stop - start
211  ).count();
212 }
213 
214 inline void Timer::resetAccumulator(unsigned int id){
215  TBTKAssert(
216  id < accumulators.size(),
217  "Timer::resetAccumulator()",
218  "'id' is out of bounds.",
219  "Ensure that the id corresponds to a value returned by a"
220  << " corresponding call to Timer::createAccumulator()."
221  );
222 
223  accumulators[id] = 0;
224 }
225 
227  for(unsigned int n = 0; n < accumulators.size(); n++)
228  accumulators[n] = 0;
229 }
230 
232  Streams::out << "============================== Accumulator table ==============================\n";
233  Streams::out << std::left << std::setw(10) << "ID" << std::setw(33) << "Time" << std::setw(100) << " Tag" << "\n";
234  for(unsigned int n = 0; n < accumulators.size(); n++){
235  long time = accumulators[n];
236 
237  long hours = time/(60ll*60ll*1000ll*1000ll*1000ll);
238  long minutes = (time/(60ll*1000ll*1000ll*1000ll))%60ll;
239  long seconds = (time/(1000ll*1000ll*1000ll))%60ll;
240  long milliseconds = (time/(1000ll*1000ll))%1000ll;
241  long microseconds = (time/(1000ll))%1000ll;
242  long nanoseconds = time%1000ll;
243 
244  const std::string &tag = accumulatorTags[n];
245 
246  Streams::out << std::left << std::setw(10) << "[" + std::to_string(n) + "]" << std::right;
247  if(hours > 0)
248  Streams::out << std::setw(6) << std::to_string(hours) + "h";
249  else
250  Streams::out << std::setw(6) << " ";
251  if(hours > 0 || minutes > 0)
252  Streams::out << std::setw(5) << std::to_string(minutes) + "m";
253  else
254  Streams::out << std::setw(5) << " ";
255  if(hours > 0 || minutes > 0 || seconds > 0)
256  Streams::out << std::setw(4) << std::to_string(seconds) + "s";
257  else
258  Streams::out << std::setw(4) << " ";
259  if(hours > 0 || minutes > 0 || seconds > 0 || milliseconds > 0)
260  Streams::out << std::setw(6) << std::to_string(milliseconds) + "ms";
261  else
262  Streams::out << std::setw(6) << " ";
263  if(hours > 0 || minutes > 0 || seconds > 0 || milliseconds > 0 || microseconds > 0)
264  Streams::out << std::setw(6) << std::to_string(microseconds) + "us";
265  else
266  Streams::out << std::setw(6) << " ";
267  if(hours > 0 || minutes > 0 || seconds > 0 || milliseconds > 0 || microseconds > 0 || nanoseconds > 0)
268  Streams::out << std::setw(6) << std::to_string(nanoseconds) + "ns";
269  else
270  Streams::out << std::setw(6) << " ";
271  Streams::out << std::left << " " << std::setw(100) << tag << "\n";
272  }
273  Streams::out << "===============================================================================\n";
274 }
275 
276 }; //End of namespace TBTK
277 
278 #endif
static void printAccumulators()
Definition: Timer.h:231
static void tick(std::string tag="")
Definition: Timer.h:134
static void tock()
Definition: Timer.h:139
Precompiler macros.
static void resetAccumulator(unsigned int id)
Definition: Timer.h:214
static std::ostream out
Definition: Streams.h:70
Definition: Boolean.h:32
static void resetAccumulators()
Definition: Timer.h:226
static unsigned int createAccumulator(const std::string &tag="")
Definition: Timer.h:174
A Timer for measuring execution time.
Definition: Timer.h:75
Streams for TBTK output.