GCC Code Coverage Report


Directory: ./
File: include/crocoddyl/core/utils/stop-watch.hpp
Date: 2025-02-24 23:41:29
Exec Total Coverage
Lines: 1 12 8.3%
Branches: 0 0 -%

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 CROCODDYL_CORE_UTILS_STOPWATCH_H_
26 #define CROCODDYL_CORE_UTILS_STOPWATCH_H_
27
28 #include <ctime>
29 #include <iostream>
30 #include <limits>
31 #include <map>
32 #include <sstream>
33
34 #ifndef WIN32
35 /* The classes below are exported */
36 #pragma GCC visibility push(default)
37 #endif
38
39 #define START_PROFILER(name) \
40 getProfiler().profiler_status() ? getProfiler().start(name) : void()
41 #define STOP_PROFILER(name) \
42 getProfiler().profiler_status() ? getProfiler().stop(name) : void()
43
44 #define STOP_WATCH_MAX_NAME_LENGTH 60
45 #define STOP_WATCH_TIME_WIDTH 10
46
47 namespace crocoddyl {
48
49 // Generic stopwatch exception class
50 struct StopwatchException {
51 public:
52 StopwatchException(std::string error) : error(error) {}
53 std::string error;
54 };
55
56 enum StopwatchMode {
57 NONE = 0, // Clock is not initialized
58 CPU_TIME = 1, // Clock calculates time ranges using ctime and CLOCKS_PER_SEC
59 REAL_TIME = 2 // Clock calculates time by asking the operating system how
60 // much real time passed
61 };
62
63 /**
64 @brief A class representing a stopwatch.
65
66 @code
67 Stopwatch swatch();
68 @endcode
69
70 The Stopwatch class can be used to measure execution time of code,
71 algorithms, etc., // TODO: he Stopwatch can be initialized in two
72 time-taking modes, CPU time and real time:
73
74 @code
75 swatch.set_mode(REAL_TIME);
76 @endcode
77
78 CPU time is the time spent by the processor on a certain piece of code,
79 while real time is the real amount of time taken by a certain piece of
80 code to execute (i.e. in general if you are doing hard work such as
81 image or video editing on a different process the measured time will
82 probably increase).
83
84 How does it work? Basically, one wraps the code to be measured with the
85 following method calls:
86
87 @code
88 swatch.start("My astounding algorithm");
89 // Hic est code
90 swatch.stop("My astounding algorithm");
91 @endcode
92
93 A string representing the code ID is provided so that nested portions of
94 code can be profiled separately:
95
96 @code
97 swatch.start("My astounding algorithm");
98
99 swatch.start("My astounding algorithm - Super smart init");
100 // Initialization
101 swatch.stop("My astounding algorithm - Super smart init");
102
103 swatch.start("My astounding algorithm - Main loop");
104 // Loop
105 swatch.stop("My astounding algorithm - Main loop");
106
107 swatch.stop("My astounding algorithm");
108 @endcode
109
110 Note: ID strings can be whatever you like, in the previous example I have
111 used "My astounding algorithm - *" only to enforce the fact that the
112 measured code portions are part of My astounding algorithm, but there's no
113 connection between the three measurements.
114
115 If the code for a certain task is scattered through different files or
116 portions of the same file one can use the start-pause-stop method:
117
118 @code
119 swatch.start("Setup");
120 // First part of setup
121 swatch.pause("Setup");
122
123 swatch.start("Main logic");
124 // Main logic
125 swatch.stop("Main logic");
126
127 swatch.start("Setup");
128 // Cleanup (part of the setup)
129 swatch.stop("Setup");
130 @endcode
131
132 Finally, to report the results of the measurements just run:
133
134 @code
135 swatch.report("Code ID");
136 @endcode
137
138 Thou can also provide an additional std::ostream& parameter to report() to
139 redirect the logging on a different output. Also, you can use the
140 get_total/min/max/average_time() methods to get the individual numeric data,
141 without all the details of the logging. You can also extend Stopwatch to
142 implement your own logging syntax.
143
144 To report all the measurements:
145
146 @code
147 swatch.report_all();
148 @endcode
149
150 Same as above, you can redirect the output by providing a std::ostream&
151 parameter.
152
153 */
154 class Stopwatch {
155 protected:
156 struct PerformanceData;
157
158 public:
159 struct Watcher {
160 Stopwatch &w;
161 std::string n;
162 PerformanceData *p;
163
164 Watcher(Stopwatch &_w, std::string _n, PerformanceData *_p)
165 : w(_w), n(_n), p(_p) {}
166 inline void start() {
167 if (w.profiler_active) _start();
168 }
169 inline void stop() {
170 if (w.profiler_active) _stop();
171 }
172
173 private:
174 void _start();
175 void _stop();
176 };
177
178 /** @brief Constructor */
179 Stopwatch(StopwatchMode _mode = NONE);
180
181 /** @brief Destructor */
182 ~Stopwatch();
183
184 /** @brief Enable the profiler **/
185 void enable_profiler();
186
187 /** @brief Disable the profiler **/
188 void disable_profiler();
189
190 /** @brief Return if the profiler is enable or disable **/
191 25637 inline bool profiler_status() { return profiler_active; }
192
193 /** @brief Tells if a performance with a certain ID exists */
194 bool performance_exists(std::string perf_name);
195
196 /** @brief Initialize stopwatch to use a certain time taking mode */
197 void set_mode(StopwatchMode mode);
198
199 /** @brief create a Start the stopwatch related to a certain piece of code */
200 Watcher watcher(const std::string &perf_name);
201
202 /** @brief Start the stopwatch related to a certain piece of code */
203 void start(const std::string &perf_name);
204
205 /** @brief Stops the stopwatch related to a certain piece of code */
206 void stop(const std::string &perf_name);
207
208 /** @brief Stops the stopwatch related to a certain piece of code */
209 void pause(const std::string &perf_name);
210
211 /** @brief Reset a certain performance record */
212 void reset(const std::string &perf_name);
213
214 /** @brief Resets all the performance records */
215 void reset_all();
216
217 /** @brief Dump the data of a certain performance record */
218 void report(const std::string &perf_name, int precision = 2,
219 std::ostream &output = std::cout);
220
221 /** @brief Dump the data of all the performance records */
222 void report_all(int precision = 2, std::ostream &output = std::cout);
223
224 /** @brief Returns total execution time of a certain performance */
225 long double get_total_time(const std::string &perf_name);
226
227 /** @brief Returns average execution time of a certain performance */
228 long double get_average_time(const std::string &perf_name);
229
230 /** @brief Returns minimum execution time of a certain performance */
231 long double get_min_time(const std::string &perf_name);
232
233 /** @brief Returns maximum execution time of a certain performance */
234 long double get_max_time(const std::string &perf_name);
235
236 /** @brief Return last measurement of a certain performance */
237 long double get_last_time(const std::string &perf_name);
238
239 /** @brief Return the time since the start of the last measurement of a given
240 performance.
241 */
242 long double get_time_so_far(const std::string &perf_name);
243
244 /** @brief Turn off clock, all the Stopwatch::* methods return without doing
245 anything after this method is called. */
246 void turn_off();
247
248 /** @brief Turn on clock, restore clock operativity after a turn_off(). */
249 void turn_on();
250
251 /** @brief Take time, depends on mode. */
252 long double take_time();
253
254 protected:
255 /** @brief Struct to hold the performance data */
256 struct PerformanceData {
257 PerformanceData()
258 : clock_start(0),
259 total_time(0),
260 min_time(std::numeric_limits<long double>::max()),
261 max_time(std::numeric_limits<long double>::min()),
262 last_time(0),
263 paused(false),
264 stops(0) {}
265
266 long double clock_start; //!< Start time
267 long double total_time; //!< Cumulative total time
268 long double min_time; //!< Minimum time
269 long double max_time; //!< Maximum time
270 long double last_time; //!< Last time
271 bool paused; //!< Tells if this performance has been paused, only for
272 //!< internal use
273 int stops; //!< How many cycles have been this stopwatch executed?
274 };
275
276 PerformanceData &get_or_create_perf(const std::string &perf_name);
277
278 void stop_perf(PerformanceData &perf_info, long double clock_end);
279
280 bool active; //!< Flag to hold the clock's status
281 StopwatchMode mode; //!< Time taking mode
282 std::map<std::string, PerformanceData>
283 *records_of; //!< Dynamic collection of performance data
284 bool profiler_active; //!< Indicates if the profiler is enabled
285 };
286
287 Stopwatch &getProfiler();
288
289 } // namespace crocoddyl
290
291 #ifndef WIN32
292 #pragma GCC visibility pop
293 #endif
294
295 #endif
296