TBTK
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 
40 class Timer{
41 public:
45  static void tick(std::string tag = "");
46 
49  static void tock();
50 
53  static unsigned int createAccumulator(const std::string &tag = "");
54 
56  static void tick(unsigned int id);
57 
59  static void tock(unsigned int id);
60 
62  static void resetAccumulator(unsigned int id);
63 
65  static void resetAccumulators();
66 
68  static void printAccumulators();
69 private:
71  static std::vector<std::chrono::time_point<std::chrono::high_resolution_clock>> timestamps;
72 
74  static std::vector<std::string> tags;
75 
77  static std::vector<std::chrono::time_point<std::chrono::high_resolution_clock>> accumulatorTimestamps;
78 
80  static std::vector<std::string> accumulatorTags;
81 
83  static std::vector<long> accumulators;
84 };
85 
86 inline void Timer::tick(std::string tag){
87  timestamps.push_back(std::chrono::high_resolution_clock::now());
88  tags.push_back(tag);
89 }
90 
91 inline void Timer::tock(){
92  std::chrono::time_point<std::chrono::high_resolution_clock> stop = std::chrono::high_resolution_clock::now();
93  if(timestamps.size() > 0){
94  std::chrono::time_point<std::chrono::high_resolution_clock> start = timestamps.back();
95  timestamps.pop_back();
96  std::string tag = tags.back();
97  tags.pop_back();
98 
99  int hours = (std::chrono::duration_cast<std::chrono::hours>(stop - start).count());
100  int minutes = (std::chrono::duration_cast<std::chrono::minutes>(stop - start).count())%60;
101  int seconds = (std::chrono::duration_cast<std::chrono::seconds>(stop - start).count())%60;
102  int milliseconds = (std::chrono::duration_cast<std::chrono::milliseconds>(stop - start).count())%1000;
103  int microseconds = (std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count())%1000;
104  int nanoseconds = (std::chrono::duration_cast<std::chrono::nanoseconds>(stop - start).count())%1000;
105 
106  Streams::out << "(" << timestamps.size() << ") ";
107  if(hours > 0)
108  Streams::out << hours << "h ";
109  if(hours > 0 || minutes > 0)
110  Streams::out << minutes << "m ";
111  if(hours > 0 || minutes > 0 || seconds > 0)
112  Streams::out << seconds << "s ";
113  if(hours > 0 || minutes > 0 || seconds > 0 || milliseconds > 0)
114  Streams::out << milliseconds << "ms ";
115  if(hours > 0 || minutes > 0 || seconds > 0 || milliseconds > 0 || microseconds > 0)
116  Streams::out << microseconds << "us ";
117  if(hours > 0 || minutes > 0 || seconds > 0 || milliseconds > 0 || microseconds > 0 || nanoseconds > 0)
118  Streams::out << nanoseconds << "ns ";
119  Streams::out << "\t" << tag << "\n";
120  }
121  else{
122  Streams::out << "Error in Time::tock(): No corresponding tick call made.\n";
123  }
124 }
125 
126 inline unsigned int Timer::createAccumulator(const std::string &tag){
127  accumulatorTimestamps.push_back(
128  std::chrono::high_resolution_clock::now()
129  );
130  accumulatorTags.push_back(tag);
131  accumulators.push_back(0);
132 
133  return accumulators.size() - 1;
134 }
135 
136 inline void Timer::tick(unsigned int id){
137  TBTKAssert(
138  id < accumulators.size(),
139  "Timer::tick()",
140  "'id' is out of bounds.",
141  "Ensure that the id corresponds to a value returned by a"
142  << " corresponding call to Timer::createAccumulator()."
143  );
144  accumulatorTimestamps[id] = std::chrono::high_resolution_clock::now();
145 }
146 
147 inline void Timer::tock(unsigned int id){
148  TBTKAssert(
149  id < accumulators.size(),
150  "Timer::tock()",
151  "'id' is out of bounds.",
152  "Ensure that the id corresponds to a value returned by a"
153  << " corresponding call to Timer::createAccumulator()."
154  );
155  std::chrono::time_point<std::chrono::high_resolution_clock> stop
156  = std::chrono::high_resolution_clock::now();
157  std::chrono::time_point<std::chrono::high_resolution_clock> start
158  = accumulatorTimestamps[id];
159 
160  accumulators[id]
161  += std::chrono::duration_cast<std::chrono::nanoseconds>(
162  stop - start
163  ).count();
164 }
165 
166 inline void Timer::resetAccumulator(unsigned int id){
167  TBTKAssert(
168  id < accumulators.size(),
169  "Timer::resetAccumulator()",
170  "'id' is out of bounds.",
171  "Ensure that the id corresponds to a value returned by a"
172  << " corresponding call to Timer::createAccumulator()."
173  );
174 
175  accumulators[id] = 0;
176 }
177 
179  for(unsigned int n = 0; n < accumulators.size(); n++)
180  accumulators[n] = 0;
181 }
182 
184  Streams::out << "============================== Accumulator table ==============================\n";
185  Streams::out << std::left << std::setw(10) << "ID" << std::setw(33) << "Time" << std::setw(100) << " Tag" << "\n";
186  for(unsigned int n = 0; n < accumulators.size(); n++){
187  long time = accumulators[n];
188 
189  long hours = time/(60ll*60ll*1000ll*1000ll*1000ll);
190  long minutes = (time/(60ll*1000ll*1000ll*1000ll))%60ll;
191  long seconds = (time/(1000ll*1000ll*1000ll))%60ll;
192  long milliseconds = (time/(1000ll*1000ll))%1000ll;
193  long microseconds = (time/(1000ll))%1000ll;
194  long nanoseconds = time%1000ll;
195 
196  const std::string &tag = accumulatorTags[n];
197 
198  Streams::out << std::left << std::setw(10) << "[" + std::to_string(n) + "]" << std::right;
199  if(hours > 0)
200  Streams::out << std::setw(6) << std::to_string(hours) + "h";
201  else
202  Streams::out << std::setw(6) << " ";
203  if(hours > 0 || minutes > 0)
204  Streams::out << std::setw(5) << std::to_string(minutes) + "m";
205  else
206  Streams::out << std::setw(5) << " ";
207  if(hours > 0 || minutes > 0 || seconds > 0)
208  Streams::out << std::setw(4) << std::to_string(seconds) + "s";
209  else
210  Streams::out << std::setw(4) << " ";
211  if(hours > 0 || minutes > 0 || seconds > 0 || milliseconds > 0)
212  Streams::out << std::setw(6) << std::to_string(milliseconds) + "ms";
213  else
214  Streams::out << std::setw(6) << " ";
215  if(hours > 0 || minutes > 0 || seconds > 0 || milliseconds > 0 || microseconds > 0)
216  Streams::out << std::setw(6) << std::to_string(microseconds) + "us";
217  else
218  Streams::out << std::setw(6) << " ";
219  if(hours > 0 || minutes > 0 || seconds > 0 || milliseconds > 0 || microseconds > 0 || nanoseconds > 0)
220  Streams::out << std::setw(6) << std::to_string(nanoseconds) + "ns";
221  else
222  Streams::out << std::setw(6) << " ";
223  Streams::out << std::left << " " << std::setw(100) << tag << "\n";
224  }
225  Streams::out << "===============================================================================\n";
226 }
227 
228 }; //End of namespace TBTK
229 
230 #endif
static void printAccumulators()
Definition: Timer.h:183
static void tick(std::string tag="")
Definition: Timer.h:86
static void tock()
Definition: Timer.h:91
Precompiler macros.
static void resetAccumulator(unsigned int id)
Definition: Timer.h:166
static std::ostream out
Definition: Streams.h:36
Definition: ModelFactory.h:35
static void resetAccumulators()
Definition: Timer.h:178
static unsigned int createAccumulator(const std::string &tag="")
Definition: Timer.h:126
Definition: Timer.h:40
Streams for TBTK output.