Crocoddyl
 
Loading...
Searching...
No Matches
stop-watch.cpp
1
2// Copyright (c) 2010-2013 Tommaso Urli (tommaso.urli@uniud.it; University of
3// Udine)
4//
5// Permission is hereby granted, free of charge, to any person obtaining
6// a copy of this software and associated documentation files (the
7// "Software"), to deal in the Software without restriction, including
8// without limitation the rights to use, copy, modify, merge, publish,
9// distribute, sublicense, and/or sell copies of the Software, and to
10// permit persons to whom the Software is furnished to do so, subject to
11// the following conditions:
12//
13// The above copyright notice and this permission notice shall be
14// included in all copies or substantial portions of the Software.
15//
16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25#ifndef WIN32
26#include <sys/time.h>
27#else
28#include <Windows.h>
29
30#include <iomanip>
31#endif
32
33#include <iomanip> // std::setprecision
34
35#include "crocoddyl/core/utils/stop-watch.hpp"
36
37using std::map;
38using std::ostringstream;
39using std::string;
40
41namespace crocoddyl {
42
43Stopwatch& getProfiler() {
44 static Stopwatch s(REAL_TIME); // alternatives are CPU_TIME and REAL_TIME
45 return s;
46}
47
48Stopwatch::Stopwatch(StopwatchMode _mode)
49 : active(true), mode(_mode), profiler_active(false) {
50 records_of = new map<string, PerformanceData>();
51}
52
54
56
58
59void Stopwatch::set_mode(StopwatchMode new_mode) { mode = new_mode; }
60
61bool Stopwatch::performance_exists(string perf_name) {
62 return (records_of->find(perf_name) != records_of->end());
63}
64
65long double Stopwatch::take_time() {
66 if (mode == CPU_TIME) {
67 // Use ctime
68 return (long double)clock();
69 } else if (mode == REAL_TIME) {
70 // Query operating system
71
72#ifdef WIN32
73 /* In case of usage under Windows */
74 FILETIME ft;
75 LARGE_INTEGER intervals;
76
77 // Get the amount of 100 nanoseconds intervals elapsed since January 1, 1601
78 // (UTC)
79 GetSystemTimeAsFileTime(&ft);
80 intervals.LowPart = ft.dwLowDateTime;
81 intervals.HighPart = ft.dwHighDateTime;
82
83 long double measure = intervals.QuadPart;
84 measure -= 116444736000000000.0; // Convert to UNIX epoch time
85 measure /= 10000000.0; // Convert to seconds
86
87 return measure;
88#else
89 /* Linux, MacOS, ... */
90 struct timeval tv;
91 gettimeofday(&tv, NULL);
92
93 long double measure = tv.tv_usec;
94 measure /= 1000000.0; // Convert to seconds
95 measure += (long double)tv.tv_sec; // Add seconds part
96 return measure;
97#endif
98
99 } else {
100 // If mode == NONE, clock has not been initialized, then throw exception
101 throw StopwatchException("Clock not initialized to a time taking mode!");
102 }
103}
104
105Stopwatch::PerformanceData& Stopwatch::get_or_create_perf(
106 const string& perf_name) {
107 const auto it = records_of->insert(make_pair(perf_name, PerformanceData()));
108 return it.first->second;
109}
110
111void Stopwatch::start(const string& perf_name) {
112 if (!active) return;
113
114 PerformanceData& perf_info = get_or_create_perf(perf_name);
115
116 // Take ctime
117 perf_info.clock_start = take_time();
118
119 // If this is a new start (i.e. not a restart)
120 // if (!perf_info.paused)
121 // perf_info.last_time = 0;
122
123 perf_info.paused = false;
124}
125
126void Stopwatch::stop(const string& perf_name) {
127 if (!active) return;
128
129 long double clock_end = take_time();
130
131 // Try to recover performance data
132 if (!performance_exists(perf_name))
133 throw StopwatchException("Performance not initialized.");
134
135 PerformanceData& perf_info = records_of->find(perf_name)->second;
136
137 stop_perf(perf_info, clock_end);
138}
139
140void Stopwatch::stop_perf(PerformanceData& perf_info, long double clock_end) {
141 // check whether the performance has been reset
142 if (perf_info.clock_start == 0) return;
143
144 perf_info.stops++;
145 long double lapse = clock_end - perf_info.clock_start;
146
147 if (mode == CPU_TIME) lapse /= (double)CLOCKS_PER_SEC;
148
149 // Update last time
150 perf_info.last_time = lapse;
151
152 // Update min/max time
153 if (lapse >= perf_info.max_time)
154 perf_info.max_time = lapse;
155 else if (lapse <= perf_info.min_time)
156 perf_info.min_time = lapse;
157
158 // Update total time
159 perf_info.total_time += lapse;
160}
161
162void Stopwatch::pause(const string& perf_name) {
163 if (!active) return;
164
165 long double clock_end = (long double)clock();
166
167 // Try to recover performance data
168 if (!performance_exists(perf_name))
169 throw StopwatchException("Performance not initialized.");
170
171 PerformanceData& perf_info = records_of->find(perf_name)->second;
172
173 // check whether the performance has been reset
174 if (perf_info.clock_start == 0) return;
175
176 long double lapse = clock_end - perf_info.clock_start;
177
178 // Update total time
179 perf_info.last_time += lapse;
180 perf_info.total_time += lapse;
181}
182
184 if (!active) return;
185
186 map<string, PerformanceData>::iterator it;
187
188 for (it = records_of->begin(); it != records_of->end(); ++it) {
189 reset(it->first);
190 }
191}
192
193void Stopwatch::report_all(int precision, std::ostream& output) {
194 if (!active) return;
195
196 output << "\n"
197 << std::setw(STOP_WATCH_MAX_NAME_LENGTH) << std::left
198 << "*** PROFILING RESULTS [ms] ";
199 output << std::setw(STOP_WATCH_TIME_WIDTH) << "min"
200 << " ";
201 output << std::setw(STOP_WATCH_TIME_WIDTH) << "avg"
202 << " ";
203 output << std::setw(STOP_WATCH_TIME_WIDTH) << "max"
204 << " ";
205 output << std::setw(STOP_WATCH_TIME_WIDTH) << "lastTime"
206 << " ";
207 output << std::setw(STOP_WATCH_TIME_WIDTH) << "nSamples"
208 << " ";
209 output << std::setw(STOP_WATCH_TIME_WIDTH) << "totalTime"
210 << " ***\n"
211 << std::flush;
212 map<string, PerformanceData>::iterator it;
213 for (it = records_of->begin(); it != records_of->end(); ++it) {
214 if (it->second.stops > 0) report(it->first, precision, output);
215 }
216}
217
218void Stopwatch::reset(const string& perf_name) {
219 if (!active) return;
220
221 // Try to recover performance data
222 if (!performance_exists(perf_name))
223 throw StopwatchException("Performance not initialized.");
224
225 PerformanceData& perf_info = records_of->find(perf_name)->second;
226
227 perf_info.clock_start = 0;
228 perf_info.total_time = 0;
229 perf_info.min_time = 0;
230 perf_info.max_time = 0;
231 perf_info.last_time = 0;
232 perf_info.paused = false;
233 perf_info.stops = 0;
234}
235
237 std::cout << "Stopwatch active." << std::endl;
238 active = true;
239}
240
242 std::cout << "Stopwatch inactive." << std::endl;
243 active = false;
244}
245
246void Stopwatch::report(const string& perf_name, int precision,
247 std::ostream& output) {
248 if (!active) return;
249
250 // Try to recover performance data
251 if (!performance_exists(perf_name))
252 throw StopwatchException("Performance not initialized.");
253
254 PerformanceData& perf_info = records_of->find(perf_name)->second;
255
256 output << std::setw(STOP_WATCH_MAX_NAME_LENGTH) << std::left << perf_name;
257 output << std::fixed << std::setprecision(precision)
258 << std::setw(STOP_WATCH_TIME_WIDTH) << (perf_info.min_time * 1e3)
259 << " ";
260 output << std::fixed << std::setprecision(precision)
261 << std::setw(STOP_WATCH_TIME_WIDTH)
262 << (perf_info.total_time * 1e3 / (long double)perf_info.stops) << " ";
263 output << std::fixed << std::setprecision(precision)
264 << std::setw(STOP_WATCH_TIME_WIDTH) << (perf_info.max_time * 1e3)
265 << " ";
266 output << std::fixed << std::setprecision(precision)
267 << std::setw(STOP_WATCH_TIME_WIDTH) << (perf_info.last_time * 1e3)
268 << " ";
269 output << std::fixed << std::setprecision(precision)
270 << std::setw(STOP_WATCH_TIME_WIDTH) << perf_info.stops << " ";
271 output << std::fixed << std::setprecision(precision)
272 << std::setw(STOP_WATCH_TIME_WIDTH) << perf_info.total_time * 1e3
273 << std::endl
274 << std::flush;
275}
276
277long double Stopwatch::get_time_so_far(const string& perf_name) {
278 // Try to recover performance data
279 if (!performance_exists(perf_name))
280 throw StopwatchException("Performance not initialized.");
281
282 long double lapse =
283 (take_time() - (records_of->find(perf_name)->second).clock_start);
284
285 if (mode == CPU_TIME) lapse /= (double)CLOCKS_PER_SEC;
286
287 return lapse;
288}
289
290long double Stopwatch::get_total_time(const string& perf_name) {
291 // Try to recover performance data
292 if (!performance_exists(perf_name))
293 throw StopwatchException("Performance not initialized.");
294
295 PerformanceData& perf_info = records_of->find(perf_name)->second;
296
297 return perf_info.total_time;
298}
299
300long double Stopwatch::get_average_time(const string& perf_name) {
301 // Try to recover performance data
302 if (!performance_exists(perf_name))
303 throw StopwatchException("Performance not initialized.");
304
305 PerformanceData& perf_info = records_of->find(perf_name)->second;
306
307 return (perf_info.total_time / (long double)perf_info.stops);
308}
309
310long double Stopwatch::get_min_time(const string& perf_name) {
311 // Try to recover performance data
312 if (!performance_exists(perf_name))
313 throw StopwatchException("Performance not initialized.");
314
315 PerformanceData& perf_info = records_of->find(perf_name)->second;
316
317 return perf_info.min_time;
318}
319
320long double Stopwatch::get_max_time(const string& perf_name) {
321 // Try to recover performance data
322 if (!performance_exists(perf_name))
323 throw StopwatchException("Performance not initialized.");
324
325 PerformanceData& perf_info = records_of->find(perf_name)->second;
326
327 return perf_info.max_time;
328}
329
330long double Stopwatch::get_last_time(const string& perf_name) {
331 // Try to recover performance data
332 if (!performance_exists(perf_name))
333 throw StopwatchException("Performance not initialized.");
334
335 PerformanceData& perf_info = records_of->find(perf_name)->second;
336
337 return perf_info.last_time;
338}
339
340Stopwatch::Watcher Stopwatch::watcher(const string& perf_name) {
341 if (!active) return Watcher(*this, perf_name, nullptr);
342
343 const auto it = records_of->insert(make_pair(perf_name, PerformanceData()));
344
345 PerformanceData* perf_info = &(it.first->second);
346
347 return Watcher(*this, perf_name, perf_info);
348}
349
350void Stopwatch::Watcher::_start() {
351 if (!w.profiler_active) return;
352
353 if (p == nullptr) {
354 p = &w.get_or_create_perf(n);
355 }
356
357 p->clock_start = w.take_time();
358 p->paused = false;
359}
360
361void Stopwatch::Watcher::_stop() {
362 if (!w.profiler_active || (p == nullptr)) return;
363
364 long double clock_end = w.take_time();
365 w.stop_perf(*p, clock_end);
366}
367
368} // end namespace crocoddyl
bool active
Flag to hold the clock's status.
long double get_total_time(const std::string &perf_name)
Returns total execution time of a certain performance.
Stopwatch(StopwatchMode _mode=NONE)
Constructor.
void reset_all()
Resets all the performance records.
long double take_time()
Take time, depends on mode.
long double get_time_so_far(const std::string &perf_name)
Return the time since the start of the last measurement of a given performance.
void stop(const std::string &perf_name)
Stops the stopwatch related to a certain piece of code.
void turn_on()
Turn on clock, restore clock operativity after a turn_off().
long double get_last_time(const std::string &perf_name)
Return last measurement of a certain performance.
std::map< std::string, PerformanceData > * records_of
Dynamic collection of performance data.
void start(const std::string &perf_name)
Start the stopwatch related to a certain piece of code.
void reset(const std::string &perf_name)
Reset a certain performance record.
Watcher watcher(const std::string &perf_name)
create a Start the stopwatch related to a certain piece of code
void disable_profiler()
Disable the profiler.
bool profiler_active
Indicates if the profiler is enabled.
void report_all(int precision=2, std::ostream &output=std::cout)
Dump the data of all the performance records.
long double get_max_time(const std::string &perf_name)
Returns maximum execution time of a certain performance.
long double get_average_time(const std::string &perf_name)
Returns average execution time of a certain performance.
void set_mode(StopwatchMode mode)
Initialize stopwatch to use a certain time taking mode.
~Stopwatch()
Destructor.
long double get_min_time(const std::string &perf_name)
Returns minimum execution time of a certain performance.
void turn_off()
Turn off clock, all the Stopwatch::* methods return without doing anything after this method is calle...
bool performance_exists(std::string perf_name)
Tells if a performance with a certain ID exists.
void pause(const std::string &perf_name)
Stops the stopwatch related to a certain piece of code.
void enable_profiler()
Enable the profiler.
StopwatchMode mode
Time taking mode.
void report(const std::string &perf_name, int precision=2, std::ostream &output=std::cout)
Dump the data of a certain performance record.
Struct to hold the performance data.
long double min_time
Minimum time.
long double max_time
Maximum time.
long double total_time
Cumulative total time.
int stops
How many cycles have been this stopwatch executed?