GCC Code Coverage Report


Directory: ./
File: src/core/utils/stop-watch.cpp
Date: 2025-02-24 23:41:29
Exec Total Coverage
Lines: 8 164 4.9%
Branches: 5 206 2.4%

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 25637 Stopwatch& getProfiler() {
44
4/8
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 25633 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
25637 static Stopwatch s(REAL_TIME); // alternatives are CPU_TIME and REAL_TIME
45 25637 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
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
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 void Stopwatch::set_mode(StopwatchMode new_mode) { mode = new_mode; }
60
61 bool Stopwatch::performance_exists(string perf_name) {
62 return (records_of->find(perf_name) != records_of->end());
63 }
64
65 long 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
105 Stopwatch::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
111 void 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
126 void 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
140 void 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
162 void 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
183 void Stopwatch::reset_all() {
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
193 void 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 map<string, PerformanceData>::iterator it;
212 for (it = records_of->begin(); it != records_of->end(); ++it) {
213 if (it->second.stops > 0) report(it->first, precision, output);
214 }
215 }
216
217 void Stopwatch::reset(const string& perf_name) {
218 if (!active) return;
219
220 // Try to recover performance data
221 if (!performance_exists(perf_name))
222 throw StopwatchException("Performance not initialized.");
223
224 PerformanceData& perf_info = records_of->find(perf_name)->second;
225
226 perf_info.clock_start = 0;
227 perf_info.total_time = 0;
228 perf_info.min_time = 0;
229 perf_info.max_time = 0;
230 perf_info.last_time = 0;
231 perf_info.paused = false;
232 perf_info.stops = 0;
233 }
234
235 void Stopwatch::turn_on() {
236 std::cout << "Stopwatch active." << std::endl;
237 active = true;
238 }
239
240 void Stopwatch::turn_off() {
241 std::cout << "Stopwatch inactive." << std::endl;
242 active = false;
243 }
244
245 void Stopwatch::report(const string& perf_name, int precision,
246 std::ostream& output) {
247 if (!active) return;
248
249 // Try to recover performance data
250 if (!performance_exists(perf_name))
251 throw StopwatchException("Performance not initialized.");
252
253 PerformanceData& perf_info = records_of->find(perf_name)->second;
254
255 output << std::setw(STOP_WATCH_MAX_NAME_LENGTH) << std::left << perf_name;
256 output << std::fixed << std::setprecision(precision)
257 << std::setw(STOP_WATCH_TIME_WIDTH) << (perf_info.min_time * 1e3)
258 << " ";
259 output << std::fixed << std::setprecision(precision)
260 << std::setw(STOP_WATCH_TIME_WIDTH)
261 << (perf_info.total_time * 1e3 / (long double)perf_info.stops) << " ";
262 output << std::fixed << std::setprecision(precision)
263 << std::setw(STOP_WATCH_TIME_WIDTH) << (perf_info.max_time * 1e3)
264 << " ";
265 output << std::fixed << std::setprecision(precision)
266 << std::setw(STOP_WATCH_TIME_WIDTH) << (perf_info.last_time * 1e3)
267 << " ";
268 output << std::fixed << std::setprecision(precision)
269 << std::setw(STOP_WATCH_TIME_WIDTH) << perf_info.stops << " ";
270 output << std::fixed << std::setprecision(precision)
271 << std::setw(STOP_WATCH_TIME_WIDTH) << perf_info.total_time * 1e3
272 << std::endl;
273 }
274
275 long double Stopwatch::get_time_so_far(const string& perf_name) {
276 // Try to recover performance data
277 if (!performance_exists(perf_name))
278 throw StopwatchException("Performance not initialized.");
279
280 long double lapse =
281 (take_time() - (records_of->find(perf_name)->second).clock_start);
282
283 if (mode == CPU_TIME) lapse /= (double)CLOCKS_PER_SEC;
284
285 return lapse;
286 }
287
288 long double Stopwatch::get_total_time(const string& perf_name) {
289 // Try to recover performance data
290 if (!performance_exists(perf_name))
291 throw StopwatchException("Performance not initialized.");
292
293 PerformanceData& perf_info = records_of->find(perf_name)->second;
294
295 return perf_info.total_time;
296 }
297
298 long double Stopwatch::get_average_time(const string& perf_name) {
299 // Try to recover performance data
300 if (!performance_exists(perf_name))
301 throw StopwatchException("Performance not initialized.");
302
303 PerformanceData& perf_info = records_of->find(perf_name)->second;
304
305 return (perf_info.total_time / (long double)perf_info.stops);
306 }
307
308 long double Stopwatch::get_min_time(const string& perf_name) {
309 // Try to recover performance data
310 if (!performance_exists(perf_name))
311 throw StopwatchException("Performance not initialized.");
312
313 PerformanceData& perf_info = records_of->find(perf_name)->second;
314
315 return perf_info.min_time;
316 }
317
318 long double Stopwatch::get_max_time(const string& perf_name) {
319 // Try to recover performance data
320 if (!performance_exists(perf_name))
321 throw StopwatchException("Performance not initialized.");
322
323 PerformanceData& perf_info = records_of->find(perf_name)->second;
324
325 return perf_info.max_time;
326 }
327
328 long double Stopwatch::get_last_time(const string& perf_name) {
329 // Try to recover performance data
330 if (!performance_exists(perf_name))
331 throw StopwatchException("Performance not initialized.");
332
333 PerformanceData& perf_info = records_of->find(perf_name)->second;
334
335 return perf_info.last_time;
336 }
337
338 Stopwatch::Watcher Stopwatch::watcher(const string& perf_name) {
339 if (!active) return Watcher(*this, perf_name, nullptr);
340
341 const auto it = records_of->insert(make_pair(perf_name, PerformanceData()));
342
343 PerformanceData* perf_info = &(it.first->second);
344
345 return Watcher(*this, perf_name, perf_info);
346 }
347
348 void Stopwatch::Watcher::_start() {
349 if (!w.profiler_active) return;
350
351 if (p == nullptr) {
352 p = &w.get_or_create_perf(n);
353 }
354
355 p->clock_start = w.take_time();
356 p->paused = false;
357 }
358
359 void Stopwatch::Watcher::_stop() {
360 if (!w.profiler_active || (p == nullptr)) return;
361
362 long double clock_end = w.take_time();
363 w.stop_perf(*p, clock_end);
364 }
365
366 } // end namespace crocoddyl
367