| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | Copyright (c) 2010-2013 Tommaso Urli | ||
| 3 | |||
| 4 | Tommaso Urli tommaso.urli@uniud.it University of Udine | ||
| 5 | |||
| 6 | Permission is hereby granted, free of charge, to any person obtaining | ||
| 7 | a copy of this software and associated documentation files (the | ||
| 8 | "Software"), to deal in the Software without restriction, including | ||
| 9 | without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | distribute, sublicense, and/or sell copies of the Software, and to | ||
| 11 | permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | the following conditions: | ||
| 13 | |||
| 14 | The above copyright notice and this permission notice shall be | ||
| 15 | included in all copies or substantial portions of the Software. | ||
| 16 | |||
| 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
| 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
| 21 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
| 22 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
| 23 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 24 | |||
| 25 | */ | ||
| 26 | |||
| 27 | #ifndef HPP_CENTROIDAL_DYNAMICS_STOP_WATCH_HH | ||
| 28 | #define HPP_CENTROIDAL_DYNAMICS_STOP_WATCH_HH | ||
| 29 | |||
| 30 | #include "hpp/centroidal-dynamics/Stdafx.hh" | ||
| 31 | |||
| 32 | #ifndef WIN32 | ||
| 33 | /* The classes below are exported */ | ||
| 34 | #pragma GCC visibility push(default) | ||
| 35 | #endif | ||
| 36 | |||
| 37 | // Generic stopwatch exception class | ||
| 38 | struct StopwatchException { | ||
| 39 | public: | ||
| 40 | ✗ | StopwatchException(std::string error) : error(error) {} | |
| 41 | std::string error; | ||
| 42 | }; | ||
| 43 | |||
| 44 | enum StopwatchMode { | ||
| 45 | NONE = 0, // Clock is not initialized | ||
| 46 | CPU_TIME = 1, // Clock calculates time ranges using ctime and CLOCKS_PER_SEC | ||
| 47 | REAL_TIME = 2 // Clock calculates time by asking the operating system how | ||
| 48 | // much real time passed | ||
| 49 | }; | ||
| 50 | |||
| 51 | /** | ||
| 52 | @brief A class representing a stopwatch. | ||
| 53 | |||
| 54 | @code | ||
| 55 | Stopwatch swatch(); | ||
| 56 | @endcode | ||
| 57 | |||
| 58 | The Stopwatch class can be used to measure execution time of code, | ||
| 59 | algorithms, etc., // TODO: he Stopwatch can be initialized in two | ||
| 60 | time-taking modes, CPU time and real time: | ||
| 61 | |||
| 62 | @code | ||
| 63 | swatch.set_mode(REAL_TIME); | ||
| 64 | @endcode | ||
| 65 | |||
| 66 | CPU time is the time spent by the processor on a certain piece of code, | ||
| 67 | while real time is the real amount of time taken by a certain piece of | ||
| 68 | code to execute (i.e. in general if you are doing hard work such as | ||
| 69 | image or video editing on a different process the measured time will | ||
| 70 | probably increase). | ||
| 71 | |||
| 72 | How does it work? Basically, one wraps the code to be measured with the | ||
| 73 | following method calls: | ||
| 74 | |||
| 75 | @code | ||
| 76 | swatch.start("My astounding algorithm"); | ||
| 77 | // Hic est code | ||
| 78 | swatch.stop("My astounding algorithm"); | ||
| 79 | @endcode | ||
| 80 | |||
| 81 | A string representing the code ID is provided so that nested portions of | ||
| 82 | code can be profiled separately: | ||
| 83 | |||
| 84 | @code | ||
| 85 | swatch.start("My astounding algorithm"); | ||
| 86 | |||
| 87 | swatch.start("My astounding algorithm - Super smart init"); | ||
| 88 | // Initialization | ||
| 89 | swatch.stop("My astounding algorithm - Super smart init"); | ||
| 90 | |||
| 91 | swatch.start("My astounding algorithm - Main loop"); | ||
| 92 | // Loop | ||
| 93 | swatch.stop("My astounding algorithm - Main loop"); | ||
| 94 | |||
| 95 | swatch.stop("My astounding algorithm"); | ||
| 96 | @endcode | ||
| 97 | |||
| 98 | Note: ID strings can be whatever you like, in the previous example I have | ||
| 99 | used "My astounding algorithm - *" only to enforce the fact that the | ||
| 100 | measured code portions are part of My astounding algorithm, but there's no | ||
| 101 | connection between the three measurements. | ||
| 102 | |||
| 103 | If the code for a certain task is scattered through different files or | ||
| 104 | portions of the same file one can use the start-pause-stop method: | ||
| 105 | |||
| 106 | @code | ||
| 107 | swatch.start("Setup"); | ||
| 108 | // First part of setup | ||
| 109 | swatch.pause("Setup"); | ||
| 110 | |||
| 111 | swatch.start("Main logic"); | ||
| 112 | // Main logic | ||
| 113 | swatch.stop("Main logic"); | ||
| 114 | |||
| 115 | swatch.start("Setup"); | ||
| 116 | // Cleanup (part of the setup) | ||
| 117 | swatch.stop("Setup"); | ||
| 118 | @endcode | ||
| 119 | |||
| 120 | Finally, to report the results of the measurements just run: | ||
| 121 | |||
| 122 | @code | ||
| 123 | swatch.report("Code ID"); | ||
| 124 | @endcode | ||
| 125 | |||
| 126 | Thou can also provide an additional std::ostream& parameter to report() to | ||
| 127 | redirect the logging on a different output. Also, you can use the | ||
| 128 | get_total/min/max/average_time() methods to get the individual numeric data, | ||
| 129 | without all the details of the logging. You can also extend Stopwatch to | ||
| 130 | implement your own logging syntax. | ||
| 131 | |||
| 132 | To report all the measurements: | ||
| 133 | |||
| 134 | @code | ||
| 135 | swatch.report_all(); | ||
| 136 | @endcode | ||
| 137 | |||
| 138 | Same as above, you can redirect the output by providing a std::ostream& | ||
| 139 | parameter. | ||
| 140 | |||
| 141 | */ | ||
| 142 | class Stopwatch { | ||
| 143 | public: | ||
| 144 | /** Constructor */ | ||
| 145 | Stopwatch(StopwatchMode _mode = NONE); | ||
| 146 | |||
| 147 | /** Destructor */ | ||
| 148 | ~Stopwatch(); | ||
| 149 | |||
| 150 | /** Tells if a performance with a certain ID exists */ | ||
| 151 | bool performance_exists(std::string perf_name); | ||
| 152 | |||
| 153 | /** Initialize stopwatch to use a certain time taking mode */ | ||
| 154 | void set_mode(StopwatchMode mode); | ||
| 155 | |||
| 156 | /** Start the stopwatch related to a certain piece of code */ | ||
| 157 | void start(std::string perf_name); | ||
| 158 | |||
| 159 | /** Stops the stopwatch related to a certain piece of code */ | ||
| 160 | void stop(std::string perf_name); | ||
| 161 | |||
| 162 | /** Stops the stopwatch related to a certain piece of code */ | ||
| 163 | void pause(std::string perf_name); | ||
| 164 | |||
| 165 | /** Reset a certain performance record */ | ||
| 166 | void reset(std::string perf_name); | ||
| 167 | |||
| 168 | /** Resets all the performance records */ | ||
| 169 | void reset_all(); | ||
| 170 | |||
| 171 | /** Dump the data of a certain performance record */ | ||
| 172 | void report(std::string perf_name, int precision = 2, | ||
| 173 | std::ostream& output = std::cout); | ||
| 174 | |||
| 175 | /** Dump the data of all the performance records */ | ||
| 176 | void report_all(int precision = 2, std::ostream& output = std::cout); | ||
| 177 | |||
| 178 | /** Returns total execution time of a certain performance */ | ||
| 179 | long double get_total_time(std::string perf_name); | ||
| 180 | |||
| 181 | /** Returns average execution time of a certain performance */ | ||
| 182 | long double get_average_time(std::string perf_name); | ||
| 183 | |||
| 184 | /** Returns minimum execution time of a certain performance */ | ||
| 185 | long double get_min_time(std::string perf_name); | ||
| 186 | |||
| 187 | /** Returns maximum execution time of a certain performance */ | ||
| 188 | long double get_max_time(std::string perf_name); | ||
| 189 | |||
| 190 | /** Return last measurement of a certain performance */ | ||
| 191 | long double get_last_time(std::string perf_name); | ||
| 192 | |||
| 193 | /** Return the time since the start of the last measurement of a given | ||
| 194 | performance. */ | ||
| 195 | long double get_time_so_far(std::string perf_name); | ||
| 196 | |||
| 197 | /** Turn off clock, all the Stopwatch::* methods return without doing | ||
| 198 | anything after this method is called. */ | ||
| 199 | void turn_off(); | ||
| 200 | |||
| 201 | /** Turn on clock, restore clock operativity after a turn_off(). */ | ||
| 202 | void turn_on(); | ||
| 203 | |||
| 204 | /** Take time, depends on mode */ | ||
| 205 | long double take_time(); | ||
| 206 | |||
| 207 | protected: | ||
| 208 | /** Struct to hold the performance data */ | ||
| 209 | struct PerformanceData { | ||
| 210 | 9040 | PerformanceData() | |
| 211 | 9040 | : clock_start(0), | |
| 212 | 9040 | total_time(0), | |
| 213 | 9040 | min_time(0), | |
| 214 | 9040 | max_time(0), | |
| 215 | 9040 | last_time(0), | |
| 216 | 9040 | paused(false), | |
| 217 | 9040 | stops(0) {} | |
| 218 | |||
| 219 | /** Start time */ | ||
| 220 | long double clock_start; | ||
| 221 | |||
| 222 | /** Cumulative total time */ | ||
| 223 | long double total_time; | ||
| 224 | |||
| 225 | /** Minimum time */ | ||
| 226 | long double min_time; | ||
| 227 | |||
| 228 | /** Maximum time */ | ||
| 229 | long double max_time; | ||
| 230 | |||
| 231 | /** Last time */ | ||
| 232 | long double last_time; | ||
| 233 | |||
| 234 | /** Tells if this performance has been paused, only for internal use */ | ||
| 235 | bool paused; | ||
| 236 | |||
| 237 | /** How many cycles have been this stopwatch executed? */ | ||
| 238 | int stops; | ||
| 239 | }; | ||
| 240 | |||
| 241 | /** Flag to hold the clock's status */ | ||
| 242 | bool active; | ||
| 243 | |||
| 244 | /** Time taking mode */ | ||
| 245 | StopwatchMode mode; | ||
| 246 | |||
| 247 | /** Pointer to the dynamic structure which holds the collection of performance | ||
| 248 | data */ | ||
| 249 | std::map<std::string, PerformanceData>* records_of; | ||
| 250 | }; | ||
| 251 | |||
| 252 | Stopwatch& getProfiler(); | ||
| 253 | |||
| 254 | #ifndef WIN32 | ||
| 255 | #pragma GCC visibility pop | ||
| 256 | #endif | ||
| 257 | |||
| 258 | #endif | ||
| 259 |