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