GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/core/utils/stop-watch.cpp Lines: 9 145 6.2 %
Date: 2024-02-13 11:12:33 Branches: 5 186 2.7 %

Line Branch Exec Source
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.
23
///////////////////////////////////////////////////////////////////////////////
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
37
using std::map;
38
using std::ostringstream;
39
using std::string;
40
41
namespace crocoddyl {
42
43
18185
Stopwatch& getProfiler() {
44


18185
  static Stopwatch s(REAL_TIME);  // alternatives are CPU_TIME and REAL_TIME
45
18185
  return s;
46
}
47
48
4
Stopwatch::Stopwatch(StopwatchMode _mode)
49
4
    : active(true), mode(_mode), profiler_active(false) {
50
4
  records_of = new map<string, PerformanceData>();
51
4
}
52
53
4
Stopwatch::~Stopwatch() { delete records_of; }
54
55
void Stopwatch::enable_profiler() { profiler_active = true; }
56
57
void Stopwatch::disable_profiler() { profiler_active = false; }
58
59
18185
bool Stopwatch::profiler_status() { return profiler_active; }
60
61
void Stopwatch::set_mode(StopwatchMode new_mode) { mode = new_mode; }
62
63
bool Stopwatch::performance_exists(string perf_name) {
64
  return (records_of->find(perf_name) != records_of->end());
65
}
66
67
long double Stopwatch::take_time() {
68
  if (mode == CPU_TIME) {
69
    // Use ctime
70
    return (long double)clock();
71
  } else if (mode == REAL_TIME) {
72
    // Query operating system
73
74
#ifdef WIN32
75
    /*	In case of usage under Windows */
76
    FILETIME ft;
77
    LARGE_INTEGER intervals;
78
79
    // Get the amount of 100 nanoseconds intervals elapsed since January 1, 1601
80
    // (UTC)
81
    GetSystemTimeAsFileTime(&ft);
82
    intervals.LowPart = ft.dwLowDateTime;
83
    intervals.HighPart = ft.dwHighDateTime;
84
85
    long double measure = intervals.QuadPart;
86
    measure -= 116444736000000000.0;  // Convert to UNIX epoch time
87
    measure /= 10000000.0;            // Convert to seconds
88
89
    return measure;
90
#else
91
    /* Linux, MacOS, ... */
92
    struct timeval tv;
93
    gettimeofday(&tv, NULL);
94
95
    long double measure = tv.tv_usec;
96
    measure /= 1000000.0;               // Convert to seconds
97
    measure += (long double)tv.tv_sec;  // Add seconds part
98
    return measure;
99
#endif
100
101
  } else {
102
    // If mode == NONE, clock has not been initialized, then throw exception
103
    throw StopwatchException("Clock not initialized to a time taking mode!");
104
  }
105
}
106
107
void Stopwatch::start(const string& perf_name) {
108
  if (!active) return;
109
110
  // Just works if not already present
111
  records_of->insert(make_pair(perf_name, PerformanceData()));
112
113
  PerformanceData& perf_info = records_of->find(perf_name)->second;
114
115
  // Take ctime
116
  perf_info.clock_start = take_time();
117
118
  // If this is a new start (i.e. not a restart)
119
  //  if (!perf_info.paused)
120
  //    perf_info.last_time = 0;
121
122
  perf_info.paused = false;
123
}
124
125
void Stopwatch::stop(const string& perf_name) {
126
  if (!active) return;
127
128
  long double clock_end = take_time();
129
130
  // Try to recover performance data
131
  if (!performance_exists(perf_name))
132
    throw StopwatchException("Performance not initialized.");
133
134
  PerformanceData& perf_info = records_of->find(perf_name)->second;
135
136
  // check whether the performance has been reset
137
  if (perf_info.clock_start == 0) return;
138
139
  perf_info.stops++;
140
  long double lapse = clock_end - perf_info.clock_start;
141
142
  if (mode == CPU_TIME) lapse /= (double)CLOCKS_PER_SEC;
143
144
  // Update last time
145
  perf_info.last_time = lapse;
146
147
  // Update min/max time
148
  if (lapse >= perf_info.max_time) perf_info.max_time = lapse;
149
  if (lapse <= perf_info.min_time || perf_info.min_time == 0)
150
    perf_info.min_time = lapse;
151
152
  // Update total time
153
  perf_info.total_time += lapse;
154
}
155
156
void Stopwatch::pause(const string& perf_name) {
157
  if (!active) return;
158
159
  long double clock_end = (long double)clock();
160
161
  // Try to recover performance data
162
  if (!performance_exists(perf_name))
163
    throw StopwatchException("Performance not initialized.");
164
165
  PerformanceData& perf_info = records_of->find(perf_name)->second;
166
167
  // check whether the performance has been reset
168
  if (perf_info.clock_start == 0) return;
169
170
  long double lapse = clock_end - perf_info.clock_start;
171
172
  // Update total time
173
  perf_info.last_time += lapse;
174
  perf_info.total_time += lapse;
175
}
176
177
void Stopwatch::reset_all() {
178
  if (!active) return;
179
180
  map<string, PerformanceData>::iterator it;
181
182
  for (it = records_of->begin(); it != records_of->end(); ++it) {
183
    reset(it->first);
184
  }
185
}
186
187
void Stopwatch::report_all(int precision, std::ostream& output) {
188
  if (!active) return;
189
190
  output << "\n"
191
         << std::setw(STOP_WATCH_MAX_NAME_LENGTH) << std::left
192
         << "*** PROFILING RESULTS [ms] ";
193
  output << std::setw(STOP_WATCH_TIME_WIDTH) << "min"
194
         << " ";
195
  output << std::setw(STOP_WATCH_TIME_WIDTH) << "avg"
196
         << " ";
197
  output << std::setw(STOP_WATCH_TIME_WIDTH) << "max"
198
         << " ";
199
  output << std::setw(STOP_WATCH_TIME_WIDTH) << "lastTime"
200
         << " ";
201
  output << std::setw(STOP_WATCH_TIME_WIDTH) << "nSamples"
202
         << " ";
203
  output << std::setw(STOP_WATCH_TIME_WIDTH) << "totalTime"
204
         << " ***\n";
205
  map<string, PerformanceData>::iterator it;
206
  for (it = records_of->begin(); it != records_of->end(); ++it) {
207
    if (it->second.stops > 0) report(it->first, precision, output);
208
  }
209
}
210
211
void Stopwatch::reset(const string& perf_name) {
212
  if (!active) return;
213
214
  // Try to recover performance data
215
  if (!performance_exists(perf_name))
216
    throw StopwatchException("Performance not initialized.");
217
218
  PerformanceData& perf_info = records_of->find(perf_name)->second;
219
220
  perf_info.clock_start = 0;
221
  perf_info.total_time = 0;
222
  perf_info.min_time = 0;
223
  perf_info.max_time = 0;
224
  perf_info.last_time = 0;
225
  perf_info.paused = false;
226
  perf_info.stops = 0;
227
}
228
229
void Stopwatch::turn_on() {
230
  std::cout << "Stopwatch active." << std::endl;
231
  active = true;
232
}
233
234
void Stopwatch::turn_off() {
235
  std::cout << "Stopwatch inactive." << std::endl;
236
  active = false;
237
}
238
239
void Stopwatch::report(const string& perf_name, int precision,
240
                       std::ostream& output) {
241
  if (!active) return;
242
243
  // Try to recover performance data
244
  if (!performance_exists(perf_name))
245
    throw StopwatchException("Performance not initialized.");
246
247
  PerformanceData& perf_info = records_of->find(perf_name)->second;
248
249
  output << std::setw(STOP_WATCH_MAX_NAME_LENGTH) << std::left << perf_name;
250
  output << std::fixed << std::setprecision(precision)
251
         << std::setw(STOP_WATCH_TIME_WIDTH) << (perf_info.min_time * 1e3)
252
         << " ";
253
  output << std::fixed << std::setprecision(precision)
254
         << std::setw(STOP_WATCH_TIME_WIDTH)
255
         << (perf_info.total_time * 1e3 / (long double)perf_info.stops) << " ";
256
  output << std::fixed << std::setprecision(precision)
257
         << std::setw(STOP_WATCH_TIME_WIDTH) << (perf_info.max_time * 1e3)
258
         << " ";
259
  output << std::fixed << std::setprecision(precision)
260
         << std::setw(STOP_WATCH_TIME_WIDTH) << (perf_info.last_time * 1e3)
261
         << " ";
262
  output << std::fixed << std::setprecision(precision)
263
         << std::setw(STOP_WATCH_TIME_WIDTH) << perf_info.stops << " ";
264
  output << std::fixed << std::setprecision(precision)
265
         << std::setw(STOP_WATCH_TIME_WIDTH) << perf_info.total_time * 1e3
266
         << std::endl;
267
}
268
269
long double Stopwatch::get_time_so_far(const string& perf_name) {
270
  // Try to recover performance data
271
  if (!performance_exists(perf_name))
272
    throw StopwatchException("Performance not initialized.");
273
274
  long double lapse =
275
      (take_time() - (records_of->find(perf_name)->second).clock_start);
276
277
  if (mode == CPU_TIME) lapse /= (double)CLOCKS_PER_SEC;
278
279
  return lapse;
280
}
281
282
long double Stopwatch::get_total_time(const string& perf_name) {
283
  // Try to recover performance data
284
  if (!performance_exists(perf_name))
285
    throw StopwatchException("Performance not initialized.");
286
287
  PerformanceData& perf_info = records_of->find(perf_name)->second;
288
289
  return perf_info.total_time;
290
}
291
292
long double Stopwatch::get_average_time(const string& perf_name) {
293
  // Try to recover performance data
294
  if (!performance_exists(perf_name))
295
    throw StopwatchException("Performance not initialized.");
296
297
  PerformanceData& perf_info = records_of->find(perf_name)->second;
298
299
  return (perf_info.total_time / (long double)perf_info.stops);
300
}
301
302
long double Stopwatch::get_min_time(const string& perf_name) {
303
  // Try to recover performance data
304
  if (!performance_exists(perf_name))
305
    throw StopwatchException("Performance not initialized.");
306
307
  PerformanceData& perf_info = records_of->find(perf_name)->second;
308
309
  return perf_info.min_time;
310
}
311
312
long double Stopwatch::get_max_time(const string& perf_name) {
313
  // Try to recover performance data
314
  if (!performance_exists(perf_name))
315
    throw StopwatchException("Performance not initialized.");
316
317
  PerformanceData& perf_info = records_of->find(perf_name)->second;
318
319
  return perf_info.max_time;
320
}
321
322
long double Stopwatch::get_last_time(const string& perf_name) {
323
  // Try to recover performance data
324
  if (!performance_exists(perf_name))
325
    throw StopwatchException("Performance not initialized.");
326
327
  PerformanceData& perf_info = records_of->find(perf_name)->second;
328
329
  return perf_info.last_time;
330
}
331
332
}  // end namespace crocoddyl