34 const std::string sFil(
"mrpt-global-profiler.csv");
35 this->saveToCSVFile(sFil);
36 std::cout <<
"[MRPT global profiler] Write stats to: " << sFil
65 bool enabled,
const std::string& name,
const bool keep_whole_history)
70 m_keep_whole_history(keep_whole_history)
96 for (
size_t p = 0; p < s.size(); p += len)
98 ret +=
rightPad(s.substr(p), len,
true);
99 if (p + len < s.size()) ret +=
"\n";
107 for (
const auto& e :
m_data)
109 TCallStats& cs = out_stats[std::string(e.first)];
110 cs.
min_t = e.second.min_t;
111 cs.
max_t = e.second.max_t;
113 cs.
mean_t = e.second.n_calls ? e.second.mean_t / e.second.n_calls : 0;
115 cs.
last_t = e.second.last_t;
125 string name_tmp =
m_name.size() != 0 ?
" "s +
m_name +
": "s :
" "s;
126 string mrpt_string =
"MRPT CTimeLogger report "s;
128 string top_header(name_tmp + mrpt_string);
131 const auto space_to_fill = top_header.size() < column_width
132 ? (column_width - top_header.size()) / 2
134 std::string dashes_half(space_to_fill,
'-');
135 top_header = dashes_half + top_header + dashes_half;
136 if (dashes_half.size() % 2)
142 std::string middle_header(
143 " FUNCTION #CALLS MIN.T MEAN.T " 145 std::string bottom_header(column_width,
'-');
147 stats_text += top_header +
"\n"s;
148 stats_text += middle_header +
"\n"s;
149 stats_text += bottom_header +
"\n"s;
152 using NameAndCallData = std::map<std::string_view, TCallData>;
153 NameAndCallData stat_strs;
154 for (
const auto& i :
m_data) stat_strs[i.first] = i.second;
168 std::string last_parent;
169 for (
const auto& i : stat_strs)
171 string line = string(i.first);
173 const auto dot_pos = line.find(
".");
174 if (dot_pos == std::string::npos)
180 const auto parent_pos = line.find(last_parent);
181 if (parent_pos != std::string::npos)
183 line =
"+-> "s + line.substr(dot_pos);
187 const string sMinT =
unitsFormat(i.second.min_t, 1,
false);
188 const string sMaxT =
unitsFormat(i.second.max_t, 1,
false);
189 const string sTotalT =
unitsFormat(i.second.mean_t, 1,
false);
191 i.second.n_calls ? i.second.mean_t / i.second.n_calls : 0, 1,
195 "%s %7u %6s%c %6s%c %6s%c %6s%c\n",
197 static_cast<unsigned int>(i.second.n_calls), sMinT.c_str(),
198 i.second.has_time_units ?
's' :
' ', sMeanT.c_str(),
199 i.second.has_time_units ?
's' :
' ', sMaxT.c_str(),
200 i.second.has_time_units ?
's' :
' ', sTotalT.c_str(),
201 i.second.has_time_units ?
's' :
' ');
204 std::string footer(top_header);
205 stats_text += footer +
"\n";
213 s +=
"FUNCTION, #CALLS, LAST.T, MIN.T, MEAN.T, MAX.T, TOTAL.T [, " 215 for (
const auto& i :
m_data)
218 "\"%.*s\",%7u,%e,%e,%e,%e,%e", static_cast<int>(i.first.size()),
219 i.first.data(),
static_cast<unsigned int>(i.second.n_calls),
220 i.second.last_t, i.second.min_t,
221 i.second.n_calls ? i.second.mean_t / i.second.n_calls : 0,
222 i.second.max_t, i.second.mean_t);
224 if (i.second.whole_history)
226 const auto& wh = i.second.whole_history.value();
227 for (
const double v : wh)
235 std::ofstream(csv_file) << s;
247 "s.whole = struct();\n\n"s;
249 std::string s_names =
"s.names={"s;
250 std::string s_counts =
"s.count=["s;
251 std::string s_mins =
"s.min=["s;
252 std::string s_maxs =
"s.max=["s;
253 std::string s_means =
"s.mean=["s;
255 for (
const auto& i :
m_data)
257 s_names +=
"'"s + i.first +
"',"s;
263 if (i.second.whole_history)
267 std::replace(clean_name.begin(), clean_name.end(),
'.',
'_');
268 std::replace(clean_name.begin(), clean_name.end(),
'-',
'_');
269 std::replace(clean_name.begin(), clean_name.end(),
'+',
'_');
270 std::replace(clean_name.begin(), clean_name.end(),
'*',
'_');
272 s +=
"s.whole."s + clean_name +
"=[";
273 const auto& wh = i.second.whole_history.value();
291 std::ofstream(file) << s;
304 std::cerr <<
"[CTimeLogger::do_enter] Warning: skipping due to hash " 310 d.open_calls.push(0);
321 std::cerr <<
"[CTimeLogger::do_enter] Warning: skipping due to hash " 327 if (!d.open_calls.empty())
347 if (!d.whole_history)
348 d.whole_history = decltype(d.whole_history)::value_type();
350 d.whole_history.value().push_back(At);
359 const std::string_view& event_name,
const double value,
360 const bool is_time) noexcept
366 std::cerr <<
"[CTimeLogger::do_enter] Warning: skipping due to hash " 375 if (++d.n_calls == 1)
388 if (!d.whole_history)
389 d.whole_history = decltype(d.whole_history)::value_type();
391 d.whole_history.value().push_back(value);
399 TDataMap::const_iterator it =
m_data.find(name);
403 return it->second.n_calls ? it->second.mean_t / it->second.n_calls : 0;
407 TDataMap::const_iterator it =
m_data.find(name);
411 return it->second.last_t;
415 const CTimeLogger& logger,
const std::string_view& section_name)
416 : m_logger(const_cast<
CTimeLogger&>(logger)), m_section_name(section_name)
436 catch (
const std::exception& e)
438 std::cerr <<
"[~CTimeLoggerEntry] Exception:\n" 453 "[CTimeLoggerSaveAtDtor] Saving stats to: `"s + name +
"`"s);
456 catch (
const std::exception& e)
458 std::cerr <<
"[~CTimeLoggerSaveAtDtor] Exception:\n" double Tac() noexcept
Stops the stopwatch.
void keep_min(T &var, const K test_val)
If the second argument is below the first one, set the first argument to this lower value...
std::string to_string(T v)
Just like std::to_string(), but with an overloaded version for std::string arguments.
void clear(bool deep_clear=false)
Resets all stats.
std::string std::string format(std::string_view fmt, ARGS &&... args)
void registerUserMeasure(const std::string_view &event_name, const double value, const bool is_time=false) noexcept
mrpt::system::CTimeLogger & m_tm
void dumpAllStats(const size_t column_width=80) const
Dump all stats through the COutputLogger interface.
std::string fileNameStripInvalidChars(const std::string &filename, const char replacement_to_invalid_chars='_')
Replace invalid filename chars by underscores ('_') or any other user-given char. ...
~MyGlobalProfiler() override
mrpt::system::CTimeLogger & global_profiler_getref() noexcept
double getLastTime(const std::string &name) const
Return the last execution time of the given "section", or 0 if it hasn'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.
static time_point now() noexcept
Returns the current time using the currently selected Clock source.
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.
static MyGlobalProfiler global_profiler
std::stack< double, std::vector< double > > open_calls
void global_profiler_enter(const char *func_name) noexcept
void saveToMFile(const std::string &m_file) const
Dump all stats to a Matlab/Octave (.m) file.
Versatile class for consistent logging and management of output messages.
bool m_keep_whole_history
const std::string m_section_name
double do_leave(const std::string_view &func_name) noexcept
CTimeLogger(bool enabled=true, const std::string &name="", const bool keep_whole_history=false)
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't ever been called "enter" wit...
void keep_max(T &var, const K test_val)
If the second argument is above the first one, set the first argument to this higher value...
#define MRPT_LOG_INFO_STREAM(__CONTENTS)
void enter(const std::string_view &func_name) noexcept
Start of a named section.
void global_profiler_leave(const char *func_name) noexcept
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
const std::string & getName() const noexcept
std::string unitsFormat(const double val, int nDecimalDigits=2, bool middle_space=true)
This function implements formatting with the appropriate SI metric unit prefix: 1e-12->'p', 1e-9->'n', 1e-6->'u', 1e-3->'m', 1->'', 1e3->'K', 1e6->'M', 1e9->'G', 1e12->'T'.
A versatile "profiler" that logs the time spent within each pair of calls to enter(X)-leave(X), among other stats.
void logStr(const VerbosityLevel level, std::string_view msg_str) const
Main method to add the specified message string to the logger.
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...
std::string aux_format_string_multilines(const std::string &s, const size_t len)
double leave(const std::string_view &func_name) noexcept
End of a named section.
std::string exception_to_str(const std::exception &e)
Builds a nice textual representation of a nested exception, which if generated using MRPT macros (THR...
std::string rightPad(const std::string &str, const size_t total_len, bool truncate_if_larger=false)
Enlarge the string with spaces up to the given length.
double timeDifference(const mrpt::system::TTimeStamp t_first, const mrpt::system::TTimeStamp t_later)
Returns the time difference from t1 to t2 (positive if t2 is posterior to t1), in seconds...
void Tic() noexcept
Starts the stopwatch.
std::string extractFileName(const std::string &filePath)
Extract just the name (without extension) of a filename from a complete path plus name plus extension...
CTimeLoggerEntry(const CTimeLogger &logger, const std::string_view §ion_name)
~CTimeLogger() override
Destructor.