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