crocoddyl  1.7.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 #include "crocoddyl/core/utils/Stdafx.hh"
25 
26 #ifndef WIN32
27 #include <sys/time.h>
28 #else
29 #include <Windows.h>
30 #include <iomanip>
31 #endif
32 
33 #include <iomanip> // std::setprecision
34 #include "crocoddyl/core/utils/stop-watch.hpp"
35 
36 using std::map;
37 using std::ostringstream;
38 using std::string;
39 
40 namespace crocoddyl {
41 
42 Stopwatch& getProfiler() {
43  static Stopwatch s(REAL_TIME); // alternatives are CPU_TIME and REAL_TIME
44  return s;
45 }
46 
47 Stopwatch::Stopwatch(StopwatchMode _mode) : active(true), mode(_mode) {
48  records_of = new map<string, PerformanceData>();
49 }
50 
52 
53 void Stopwatch::set_mode(StopwatchMode new_mode) { mode = new_mode; }
54 
55 bool Stopwatch::performance_exists(string perf_name) { return (records_of->find(perf_name) != records_of->end()); }
56 
57 long double Stopwatch::take_time() {
58  if (mode == CPU_TIME) {
59  // Use ctime
60  return clock();
61 
62  } else if (mode == REAL_TIME) {
63  // Query operating system
64 
65 #ifdef WIN32
66  /* In case of usage under Windows */
67  FILETIME ft;
68  LARGE_INTEGER intervals;
69 
70  // Get the amount of 100 nanoseconds intervals elapsed since January 1, 1601
71  // (UTC)
72  GetSystemTimeAsFileTime(&ft);
73  intervals.LowPart = ft.dwLowDateTime;
74  intervals.HighPart = ft.dwHighDateTime;
75 
76  long double measure = intervals.QuadPart;
77  measure -= 116444736000000000.0; // Convert to UNIX epoch time
78  measure /= 10000000.0; // Convert to seconds
79 
80  return measure;
81 #else
82  /* Linux, MacOS, ... */
83  struct timeval tv;
84  gettimeofday(&tv, NULL);
85 
86  long double measure = tv.tv_usec;
87  measure /= 1000000.0; // Convert to seconds
88  measure += tv.tv_sec; // Add seconds part
89 
90  return measure;
91 #endif
92 
93  } else {
94  // If mode == NONE, clock has not been initialized, then throw exception
95  throw StopwatchException("Clock not initialized to a time taking mode!");
96  }
97 }
98 
99 void Stopwatch::start(const string& perf_name) {
100  if (!active) return;
101 
102  // Just works if not already present
103  records_of->insert(make_pair(perf_name, PerformanceData()));
104 
105  PerformanceData& perf_info = records_of->find(perf_name)->second;
106 
107  // Take ctime
108  perf_info.clock_start = take_time();
109 
110  // If this is a new start (i.e. not a restart)
111  // if (!perf_info.paused)
112  // perf_info.last_time = 0;
113 
114  perf_info.paused = false;
115 }
116 
117 void Stopwatch::stop(const string& perf_name) {
118  if (!active) return;
119 
120  long double clock_end = take_time();
121 
122  // Try to recover performance data
123  if (!performance_exists(perf_name)) throw StopwatchException("Performance not initialized.");
124 
125  PerformanceData& perf_info = records_of->find(perf_name)->second;
126 
127  // check whether the performance has been reset
128  if (perf_info.clock_start == 0) return;
129 
130  perf_info.stops++;
131  long double lapse = clock_end - perf_info.clock_start;
132 
133  if (mode == CPU_TIME) lapse /= (double)CLOCKS_PER_SEC;
134 
135  // Update last time
136  perf_info.last_time = lapse;
137 
138  // Update min/max time
139  if (lapse >= perf_info.max_time) perf_info.max_time = lapse;
140  if (lapse <= perf_info.min_time || perf_info.min_time == 0) perf_info.min_time = lapse;
141 
142  // Update total time
143  perf_info.total_time += lapse;
144 }
145 
146 void Stopwatch::pause(const string& perf_name) {
147  if (!active) return;
148 
149  long double clock_end = clock();
150 
151  // Try to recover performance data
152  if (!performance_exists(perf_name)) throw StopwatchException("Performance not initialized.");
153 
154  PerformanceData& perf_info = records_of->find(perf_name)->second;
155 
156  // check whether the performance has been reset
157  if (perf_info.clock_start == 0) return;
158 
159  long double lapse = clock_end - perf_info.clock_start;
160 
161  // Update total time
162  perf_info.last_time += lapse;
163  perf_info.total_time += lapse;
164 }
165 
167  if (!active) return;
168 
169  map<string, PerformanceData>::iterator it;
170 
171  for (it = records_of->begin(); it != records_of->end(); ++it) {
172  reset(it->first);
173  }
174 }
175 
176 void Stopwatch::report_all(int precision, std::ostream& output) {
177  if (!active) return;
178 
179  output << "\n" << std::setw(STOP_WATCH_MAX_NAME_LENGTH) << std::left << "*** PROFILING RESULTS [ms] ";
180  output << std::setw(STOP_WATCH_TIME_WIDTH) << "min"
181  << " ";
182  output << std::setw(STOP_WATCH_TIME_WIDTH) << "avg"
183  << " ";
184  output << std::setw(STOP_WATCH_TIME_WIDTH) << "max"
185  << " ";
186  output << std::setw(STOP_WATCH_TIME_WIDTH) << "lastTime"
187  << " ";
188  output << std::setw(STOP_WATCH_TIME_WIDTH) << "nSamples"
189  << " ";
190  output << std::setw(STOP_WATCH_TIME_WIDTH) << "totalTime"
191  << " ***\n";
192  map<string, PerformanceData>::iterator it;
193  for (it = records_of->begin(); it != records_of->end(); ++it) {
194  if (it->second.stops > 0) report(it->first, precision, output);
195  }
196 }
197 
198 void Stopwatch::reset(const string& perf_name) {
199  if (!active) return;
200 
201  // Try to recover performance data
202  if (!performance_exists(perf_name)) throw StopwatchException("Performance not initialized.");
203 
204  PerformanceData& perf_info = records_of->find(perf_name)->second;
205 
206  perf_info.clock_start = 0;
207  perf_info.total_time = 0;
208  perf_info.min_time = 0;
209  perf_info.max_time = 0;
210  perf_info.last_time = 0;
211  perf_info.paused = false;
212  perf_info.stops = 0;
213 }
214 
216  std::cout << "Stopwatch active." << std::endl;
217  active = true;
218 }
219 
221  std::cout << "Stopwatch inactive." << std::endl;
222  active = false;
223 }
224 
225 void Stopwatch::report(const string& perf_name, int precision, std::ostream& output) {
226  if (!active) return;
227 
228  // Try to recover performance data
229  if (!performance_exists(perf_name)) throw StopwatchException("Performance not initialized.");
230 
231  PerformanceData& perf_info = records_of->find(perf_name)->second;
232 
233  output << std::setw(STOP_WATCH_MAX_NAME_LENGTH) << std::left << perf_name;
234  output << std::fixed << std::setprecision(precision) << std::setw(STOP_WATCH_TIME_WIDTH)
235  << (perf_info.min_time * 1e3) << " ";
236  output << std::fixed << std::setprecision(precision) << std::setw(STOP_WATCH_TIME_WIDTH)
237  << (perf_info.total_time * 1e3 / (long double)perf_info.stops) << " ";
238  output << std::fixed << std::setprecision(precision) << std::setw(STOP_WATCH_TIME_WIDTH)
239  << (perf_info.max_time * 1e3) << " ";
240  output << std::fixed << std::setprecision(precision) << std::setw(STOP_WATCH_TIME_WIDTH)
241  << (perf_info.last_time * 1e3) << " ";
242  output << std::fixed << std::setprecision(precision) << std::setw(STOP_WATCH_TIME_WIDTH) << perf_info.stops << " ";
243  output << std::fixed << std::setprecision(precision) << std::setw(STOP_WATCH_TIME_WIDTH)
244  << perf_info.total_time * 1e3 << std::endl;
245 }
246 
247 long double Stopwatch::get_time_so_far(const string& perf_name) {
248  // Try to recover performance data
249  if (!performance_exists(perf_name)) throw StopwatchException("Performance not initialized.");
250 
251  long double lapse = (take_time() - (records_of->find(perf_name)->second).clock_start);
252 
253  if (mode == CPU_TIME) lapse /= (double)CLOCKS_PER_SEC;
254 
255  return lapse;
256 }
257 
258 long double Stopwatch::get_total_time(const string& perf_name) {
259  // Try to recover performance data
260  if (!performance_exists(perf_name)) throw StopwatchException("Performance not initialized.");
261 
262  PerformanceData& perf_info = records_of->find(perf_name)->second;
263 
264  return perf_info.total_time;
265 }
266 
267 long double Stopwatch::get_average_time(const string& perf_name) {
268  // Try to recover performance data
269  if (!performance_exists(perf_name)) throw StopwatchException("Performance not initialized.");
270 
271  PerformanceData& perf_info = records_of->find(perf_name)->second;
272 
273  return (perf_info.total_time / (long double)perf_info.stops);
274 }
275 
276 long double Stopwatch::get_min_time(const string& perf_name) {
277  // Try to recover performance data
278  if (!performance_exists(perf_name)) throw StopwatchException("Performance not initialized.");
279 
280  PerformanceData& perf_info = records_of->find(perf_name)->second;
281 
282  return perf_info.min_time;
283 }
284 
285 long double Stopwatch::get_max_time(const string& perf_name) {
286  // Try to recover performance data
287  if (!performance_exists(perf_name)) throw StopwatchException("Performance not initialized.");
288 
289  PerformanceData& perf_info = records_of->find(perf_name)->second;
290 
291  return perf_info.max_time;
292 }
293 
294 long double Stopwatch::get_last_time(const string& perf_name) {
295  // Try to recover performance data
296  if (!performance_exists(perf_name)) throw StopwatchException("Performance not initialized.");
297 
298  PerformanceData& perf_info = records_of->find(perf_name)->second;
299 
300  return perf_info.last_time;
301 }
302 
303 } // end namespace crocoddyl
void start(const std::string &perf_name)
Start the stopwatch related to a certain piece of code.
Definition: stop-watch.cpp:99
void reset_all()
Resets all the performance records.
Definition: stop-watch.cpp:166
long double clock_start
Start time.
Definition: stop-watch.hpp:226
long double take_time()
Take time, depends on mode.
Definition: stop-watch.cpp:57
void reset(const std::string &perf_name)
Reset a certain performance record.
Definition: stop-watch.cpp:198
Struct to hold the performance data.
Definition: stop-watch.hpp:222
void turn_on()
Turn on clock, restore clock operativity after a turn_off().
Definition: stop-watch.cpp:215
~Stopwatch()
Destructor.
Definition: stop-watch.cpp:51
void report_all(int precision=2, std::ostream &output=std::cout)
Dump the data of all the performance records.
Definition: stop-watch.cpp:176
Stopwatch(StopwatchMode _mode=NONE)
Constructor.
Definition: stop-watch.cpp:47
long double get_min_time(const std::string &perf_name)
Returns minimum execution time of a certain performance.
Definition: stop-watch.cpp:276
int stops
How many cycles have been this stopwatch executed?
Definition: stop-watch.hpp:232
long double max_time
Maximum time.
Definition: stop-watch.hpp:229
long double get_total_time(const std::string &perf_name)
Returns total execution time of a certain performance.
Definition: stop-watch.cpp:258
long double get_average_time(const std::string &perf_name)
Returns average execution time of a certain performance.
Definition: stop-watch.cpp:267
long double min_time
Minimum time.
Definition: stop-watch.hpp:228
bool performance_exists(std::string perf_name)
Tells if a performance with a certain ID exists.
Definition: stop-watch.cpp:55
long double last_time
Last time.
Definition: stop-watch.hpp:230
long double total_time
Cumulative total time.
Definition: stop-watch.hpp:227
StopwatchMode mode
Time taking mode.
Definition: stop-watch.hpp:236
void turn_off()
Turn off clock, all the Stopwatch::* methods return without doing anything after this method is calle...
Definition: stop-watch.cpp:220
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:247
void set_mode(StopwatchMode mode)
Initialize stopwatch to use a certain time taking mode.
Definition: stop-watch.cpp:53
void stop(const std::string &perf_name)
Stops the stopwatch related to a certain piece of code.
Definition: stop-watch.cpp:117
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:225
bool active
Flag to hold the clock&#39;s status.
Definition: stop-watch.hpp:235
std::map< std::string, PerformanceData > * records_of
Dynamic collection of performance data.
Definition: stop-watch.hpp:237
void pause(const std::string &perf_name)
Stops the stopwatch related to a certain piece of code.
Definition: stop-watch.cpp:146
long double get_max_time(const std::string &perf_name)
Returns maximum execution time of a certain performance.
Definition: stop-watch.cpp:285
bool paused
Tells if this performance has been paused, only for internal use.
Definition: stop-watch.hpp:231
long double get_last_time(const std::string &perf_name)
Return last measurement of a certain performance.
Definition: stop-watch.cpp:294