56 _tmBegin=std::chrono::high_resolution_clock::now();
59 return std::chrono::duration<double>(std::chrono::high_resolution_clock::now()-_tmBegin).count();
62 double Tac(){
return Toc();}
64 static double timestamp(){
65 return std::chrono::duration<double>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
69 std::chrono::high_resolution_clock::time_point _tmBegin;
75 Rate(
double frequency=1.0)
78 _tmBegin=std::chrono::system_clock::now();
81 static void sleep(
double seconds)
84 std::this_thread::sleep_for(std::chrono::duration<double>(seconds));
88 std::chrono::system_clock::time_point now=std::chrono::system_clock::now();
89 sleep(_cycle-std::chrono::duration<double>(now-_tmBegin).count());
94 std::chrono::system_clock::time_point _tmBegin;
108 double min_t,max_t,mean_t;
109 std::stack<double,std::vector<double> > open_calls;
113 std::map<std::string,TCallData> m_data;
114 mutable std::mutex mMutex;
116 void do_enter(
const char *func_name );
117 double do_leave(
const char *func_name );
120 Timer(
bool enabled=
true):m_enabled(enabled){Tic();}
123 static Timer& instance(){
124 static std::shared_ptr<Timer> globalTimer(
new Timer());
128 void enable(
bool enabled =
true) { m_enabled = enabled; }
129 void disable() { m_enabled =
false; }
132 inline void enter(
const char *func_name ) {
138 inline double leave(
const char *func_name ) {
139 return m_enabled ? do_leave(func_name) : 0;
143 double getMeanTime(
const std::string &name)
const;
144 std::string getStatsAsText(
const size_t column_width=80)
const;
145 void dumpAllStats(
const size_t column_width=80)
const;
153 :_func_name(func_name){Timer::instance().enter(func_name);}
154 ~
ScopedTimer(){Timer::instance().leave(_func_name);}
155 const char* _func_name;
160 inline Timer::TCallData::TCallData() :
170 inline Timer::~Timer()
177 inline void Timer::do_enter(
const char *func_name)
180 const string s = func_name;
183 std::unique_lock<std::mutex> lock(mMutex);
184 map<string,TCallData>::iterator it=m_data.find(s);
187 it=m_data.insert(make_pair(s,TCallData())).first;
193 d->open_calls.push(0);
194 d->open_calls.top() = Tac();
197 inline double Timer::do_leave(
const char *func_name)
200 const double tim = Tac();
202 const string s = func_name;
205 std::unique_lock<std::mutex> lock(mMutex);
208 if (!d->open_calls.empty())
210 const double At = tim - d->open_calls.top();
221 if (d->min_t>At) d->min_t = At;
222 if (d->max_t<At) d->max_t = At;
232 std::unique_lock<std::mutex> lock(mMutex);
233 map<string,TCallData>::const_iterator it = m_data.find(name);
234 if (it==m_data.end())
236 else return it->second.n_calls ? it->second.mean_t/it->second.n_calls : 0;
239 inline std::string unitsFormat(
const double val,
int nDecimalDigits,
bool middle_space)
246 {mult=1e-12; prefix=
'T';}
248 {mult=1e-9; prefix=
'G';}
250 {mult=1e-6; prefix=
'M';}
252 {mult=1e-3; prefix=
'K';}
254 {mult=1; prefix=
' ';}
256 {mult=1e+3; prefix=
'm';}
258 {mult=1e+6; prefix=
'u';}
260 {mult=1e+9; prefix=
'n';}
262 {mult=1e+12; prefix=
'p';}
264 {mult=0; prefix=
'p';}
267 ost<<setw(5) <<setiosflags(ios::fixed) <<setiosflags(ios::right)
268 << setprecision(1)<<(val*mult);
270 return ost.str()+char(prefix);
273 inline std::string rightPad(
const std::string &str,
const size_t total_len,
bool truncate_if_larger)
276 if (r.size()<total_len || truncate_if_larger)
277 r.resize(total_len,
' ');
281 inline std::string aux_format_string_multilines(
const std::string &s,
const size_t len)
285 for (
size_t p=0;p<s.size();p+=len)
287 ret+=rightPad(s.c_str()+p,len,
true);
296 std::unique_lock<std::mutex> lock(mMutex);
299 ost<<
"------------------------------------ Timer report ------------------------------------\n";
300 ost<<
" FUNCTION #CALLS MIN.T MEAN.T MAX.T TOTAL \n";
301 ost<<
"---------------------------------------------------------------------------------------\n";
302 for (map<string,TCallData>::const_iterator i=m_data.begin();i!=m_data.end();++i)
304 const string sMinT = unitsFormat(i->second.min_t,1,
false);
305 const string sMaxT = unitsFormat(i->second.max_t,1,
false);
306 const string sTotalT = unitsFormat(i->second.mean_t,1,
false);
307 const string sMeanT = unitsFormat(i->second.n_calls ? i->second.mean_t/i->second.n_calls : 0,1,
false);
309 ost << aux_format_string_multilines(i->first,39)
310 <<
" " << setw(6) << setiosflags(ios::right) << i->second.n_calls <<
" " 311 << sMinT <<
"s " << sMeanT <<
"s " << sMaxT <<
"s " 315 ost<<
"--------------------------------- End of Timer report ---------------------------------\n";
323 if(!m_data.size()||!m_enabled)
return;
324 string s = getStatsAsText(column_width);
void enter(const char *func_name)
Start of a named section.
Definition: Timer.h:132
double leave(const char *func_name)
End of a named section.
Definition: Timer.h:138
std::string getStatsAsText(const size_t column_width=80) const
Dump all stats to a multi-line text string.
Definition: Timer.h:294
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...
Definition: Timer.h:229
void dumpAllStats(const size_t column_width=80) const
Dump all stats through the CDebugOutputCapable interface.
Definition: Timer.h:320