MRPT  2.0.2
system/CTimeLogger.h
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2020, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 #pragma once
10 
12 #include <mrpt/core/exceptions.h>
14 #include <mrpt/system/CTicTac.h>
15 #include <deque>
16 #include <map>
17 #include <optional>
18 #include <stack>
19 #include <vector>
20 
21 namespace mrpt::system
22 {
23 /** A versatile "profiler" that logs the time spent within each pair of calls to
24  * enter(X)-leave(X), among other stats.
25  * The results can be dumped to cout or to Visual Studio's output panel.
26  * This class can be also used to monitorize min/mean/max/total stats of any
27  * user-provided parameters via the method CTimeLogger::registerUserMeasure().
28  *
29  * Optional recording of **all** data can be enabled via
30  * enableKeepWholeHistory() (use with caution!).
31  *
32  * Cost of the profiler itself (measured on MSVC2015, Windows 10, Intel i5-2310
33  * 2.9GHz):
34  * - `enter()`: average 445 ns
35  * - `leave()`: average 316 ns
36  *
37  * Recursive methods are supported with no problems, that is, calling "enter(X)
38  * enter(X) ... leave(X) leave(X)".
39  * `enter()`/`leave()` are thread-safe, in the sense of they being safe to be
40  * called from different threads. However, calling `enter()`/`leave()` for the
41  * same user-supplied "section name", from different threads, is not allowed. In
42  * the latter case (and, actually, in general since it's safer against
43  * exceptions), use the RAII helper class CTimeLoggerEntry.
44  *
45  * \sa CTimeLoggerEntry
46  *
47  * \note The default behavior is dumping all the information at destruction.
48  * \ingroup mrpt_system_grp
49  */
51 {
52  private:
54  bool m_enabled;
55  std::string m_name;
56  bool m_keep_whole_history{false};
57 
58  //! Data of all the calls:
59  struct TCallData
60  {
61  TCallData();
62 
63  size_t n_calls{0};
64  double min_t{0}, max_t{0}, mean_t{0}, last_t{0};
65  std::stack<double, std::vector<double>> open_calls;
66  bool has_time_units{true};
67  std::optional<std::deque<double>> whole_history{};
68  };
69 
70  protected:
71  constexpr static unsigned int HASH_SIZE_IN_BYTES = 1;
72  constexpr static unsigned int HASH_ALLOWED_COLLISIONS = 10;
73  // Note: we CANNOT store a std::string_view here due to literals life scope.
76 
78 
79  void do_enter(const std::string_view& func_name) noexcept;
80  double do_leave(const std::string_view& func_name) noexcept;
81 
82  public:
83  /** Data of each call section: # of calls, minimum, maximum, average and
84  * overall execution time (in seconds) \sa getStats */
85  struct TCallStats
86  {
87  size_t n_calls{0};
88  double min_t{0}, max_t{0}, mean_t{0}, total_t{0}, last_t{0};
89  };
90 
92  bool enabled = true, const std::string& name = "",
93  const bool keep_whole_history = false);
94  /** Destructor */
95  ~CTimeLogger() override;
96 
97  // We must define these 4 because of the definition of a virtual dtor
98  // (compiler will not generate the defaults)
99  CTimeLogger(const CTimeLogger& o) = default;
100  CTimeLogger& operator=(const CTimeLogger& o) = default;
101  CTimeLogger(CTimeLogger&& o) = default;
102  CTimeLogger& operator=(CTimeLogger&& o) = default;
103 
104  /** Dump all stats to a multi-line text string. \sa dumpAllStats,
105  * saveToCVSFile */
106  std::string getStatsAsText(const size_t column_width = 80) const;
107  /** Returns all the current stats as a map: section_name => stats. \sa
108  * getStatsAsText, dumpAllStats, saveToCVSFile */
109  void getStats(std::map<std::string, TCallStats>& out_stats) const;
110  /** Dump all stats through the COutputLogger interface. \sa getStatsAsText,
111  * saveToCVSFile */
112  void dumpAllStats(const size_t column_width = 80) const;
113  /** Resets all stats. By default (deep_clear=false), all section names are
114  * remembered (not freed) so the cost of creating upon the first next call
115  * is avoided. */
116  void clear(bool deep_clear = false);
117  void enable(bool enabled = true) { m_enabled = enabled; }
118  void disable() { m_enabled = false; }
119  bool isEnabled() const { return m_enabled; }
120 
121  void enableKeepWholeHistory(bool enable = true)
122  {
124  }
126 
127  /** Dump all stats to a Comma Separated Values (CSV) file. \sa dumpAllStats
128  */
129  void saveToCSVFile(const std::string& csv_file) const;
130  /** Dump all stats to a Matlab/Octave (.m) file. \sa dumpAllStats */
131  void saveToMFile(const std::string& m_file) const;
132  void registerUserMeasure(
133  const std::string_view& event_name, const double value,
134  const bool is_time = false) noexcept;
135 
136  const std::string& getName() const noexcept { return m_name; }
137  void setName(const std::string& name) noexcept { m_name = name; }
138 
139  /** Start of a named section \sa enter */
140  inline void enter(const std::string_view& func_name) noexcept
141  {
142  if (m_enabled) do_enter(func_name);
143  }
144  /** End of a named section \return The ellapsed time, in seconds or 0 if
145  * disabled. \sa enter */
146  inline double leave(const std::string_view& func_name) noexcept
147  {
148  return m_enabled ? do_leave(func_name) : 0;
149  }
150  /** Return the mean execution time of the given "section", or 0 if it hasn't
151  * ever been called "enter" with that section name */
152  double getMeanTime(const std::string& name) const;
153  /** Return the last execution time of the given "section", or 0 if it hasn't
154  * ever been called "enter" with that section name */
155  double getLastTime(const std::string& name) const;
156 }; // End of class def.
157 
158 /** A safe way to call enter() and leave() of a mrpt::system::CTimeLogger upon
159  * construction and destruction of
160  * this auxiliary object, making sure that leave() will be called upon
161  * exceptions, etc.
162  * Usage mode #1 (scoped):
163  * \code
164  * CTimeLogger logger;
165  * // ...
166  * { // Start of scope to be monitorized
167  * CTimeLoggerEntry tle(logger,"operation-name");
168  *
169  * // do whatever
170  *
171  * } // End of scope
172  * // **DO NOT** call tle.stop() explicitly here, it's called by its dtor
173  * \endcode
174  *
175  * Usage mode #2 (unscoped):
176  * \code
177  * CTimeLogger logger;
178  * // ...
179  *
180  * CTimeLoggerEntry tle(logger,"operation-name");
181  * // do whatever
182  * tle.stop();
183  *
184  * // tle dtor does nothing else, since you already called stop()
185  * \endcode
186  *
187  * \ingroup mrpt_system_grp
188  */
190 {
192  const CTimeLogger& logger, const std::string_view& section_name);
195  void stop(); //!< for correct use, see docs for CTimeLoggerEntry
196 
197  private:
198  // Note we cannot store the string_view since we have no guarantees of the
199  // life-time of the provided string buffer.
200  const std::string m_section_name;
202  bool stopped_{false};
203 };
204 
205 /** A helper class to save CSV stats upon self destruction, for example, at the
206  * end of a program run. The target file will be named after timelogger's name.
207  * \ingroup mrpt_system_grp
208  */
210 {
212 
215 };
216 
217 /** @name Auxiliary stuff for the global profiler used in MRPT_START / MRPT_END
218  macros.
219  @{ */
220 void global_profiler_enter(const char* func_name) noexcept;
221 void global_profiler_leave(const char* func_name) noexcept;
223 /** @} */
224 
225 } // namespace mrpt::system
bool stopped_
std::chrono::time_point< Clock > time_point
Definition: Clock.h:25
A safe way to call enter() and leave() of a mrpt::system::CTimeLogger upon construction and destructi...
void clear(bool deep_clear=false)
Resets all stats.
Definition: CTimeLogger.cpp:82
void registerUserMeasure(const std::string_view &event_name, const double value, const bool is_time=false) noexcept
CTimeLogger & m_logger
mrpt::system::CTimeLogger & m_tm
void dumpAllStats(const size_t column_width=80) const
Dump all stats through the COutputLogger interface.
A high-performance stopwatch, with typical resolution of nanoseconds.
STL namespace.
mrpt::system::CTimeLogger & global_profiler_getref() noexcept
Definition: CTimeLogger.cpp:53
double getLastTime(const std::string &name) const
Return the last execution time of the given "section", or 0 if it hasn&#39;t ever been called "enter" wit...
void getStats(std::map< std::string, TCallStats > &out_stats) const
Returns all the current stats as a map: section_name => stats.
void stop()
for correct use, see docs for CTimeLoggerEntry
std::string getStatsAsText(const size_t column_width=80) const
Dump all stats to a multi-line text string.
std::stack< double, std::vector< double > > open_calls
void global_profiler_enter(const char *func_name) noexcept
Definition: CTimeLogger.cpp:54
void saveToMFile(const std::string &m_file) const
Dump all stats to a Matlab/Octave (.m) file.
std::optional< std::deque< double > > whole_history
Versatile class for consistent logging and management of output messages.
const std::string m_section_name
static constexpr unsigned int HASH_ALLOWED_COLLISIONS
void setName(const std::string &name) noexcept
double do_leave(const std::string_view &func_name) noexcept
CTimeLogger(bool enabled=true, const std::string &name="", const bool keep_whole_history=false)
Definition: CTimeLogger.cpp:64
ts_hash_map()=default
< Default constructor */
A helper class to save CSV stats upon self destruction, for example, at the end of a program run...
mrpt::Clock::time_point m_entry
void do_enter(const std::string_view &func_name) noexcept
double getMeanTime(const std::string &name) const
Return the mean execution time of the given "section", or 0 if it hasn&#39;t ever been called "enter" wit...
void enableKeepWholeHistory(bool enable=true)
void enable(bool enabled=true)
void enter(const std::string_view &func_name) noexcept
Start of a named section.
void global_profiler_leave(const char *func_name) noexcept
Definition: CTimeLogger.cpp:58
const std::string & getName() const noexcept
mrpt::containers::ts_hash_map< std::string, TCallData, HASH_SIZE_IN_BYTES, HASH_ALLOWED_COLLISIONS > TDataMap
A versatile "profiler" that logs the time spent within each pair of calls to enter(X)-leave(X), among other stats.
void saveToCSVFile(const std::string &csv_file) const
Dump all stats to a Comma Separated Values (CSV) file.
void deep_clear(CONTAINER &c)
Deep clear for a std vector container.
Data of each call section: # of calls, minimum, maximum, average and overall execution time (in secon...
double leave(const std::string_view &func_name) noexcept
End of a named section.
CTimeLoggerSaveAtDtor(mrpt::system::CTimeLogger &tm)
~CTimeLoggerEntry()
static constexpr unsigned int HASH_SIZE_IN_BYTES
CTimeLoggerEntry(const CTimeLogger &logger, const std::string_view &section_name)
~CTimeLogger() override
Destructor.
Definition: CTimeLogger.cpp:75
CTimeLogger & operator=(const CTimeLogger &o)=default



Page generated by Doxygen 1.8.14 for MRPT 2.0.2 Git: 9b4fd2465 Mon May 4 16:59:08 2020 +0200 at lun may 4 17:26:07 CEST 2020