24#include <core/exceptions/software.h>
25#include <core/exceptions/system.h>
26#include <utils/time/tracker.h>
70 if (add_default_class) {
71 class_times_.push_back(vector<struct timeval *>());
72 class_names_.push_back(
"Default");
84 if (add_default_class) {
85 class_times_.push_back(vector<struct timeval *>());
86 class_names_.push_back(
"Default");
88 timelog_ = fopen(filename,
"w");
101 class_times_.clear();
102 class_names_.clear();
112 tracker_comment_ = comment;
113 for (vector<vector<struct timeval *>>::iterator i = class_times_.begin(); i != class_times_.end();
115 for (vector<struct timeval *>::iterator j = i->begin(); j != i->end(); ++j) {
122 gettimeofday(&start_time, NULL);
123 gettimeofday(&last_time, NULL);
134 timeval *t = (timeval *)malloc(
sizeof(timeval));
135 gettimeofday(t, NULL);
137 if (!comment.empty()) {
138 comments_[times_.size() - 1] = comment;
152 throw Exception(
"TimeTracker::add_class(): Class name may not be empty");
154 class_times_.push_back(vector<struct timeval *>());
155 class_names_.push_back(name);
156 return class_times_.size() - 1;
168 if (cls < class_names_.size()) {
169 class_names_[cls] =
"";
171 if (class_times_.size() == 0) {
172 throw Exception(
"No classes have been added, cannot delete class %u", cls);
187 timeval *t = (timeval *)malloc(
sizeof(timeval));
188 gettimeofday(t, NULL);
190 long sec = t->tv_sec - last_time.tv_sec;
191 long usec = t->tv_usec - last_time.tv_usec;
196 last_time.tv_sec = t->tv_sec;
197 last_time.tv_usec = t->tv_usec;
202 if (cls < class_times_.size()) {
203 class_times_[cls].push_back(t);
205 if (class_times_.size() == 0) {
206 throw Exception(
"No classes have been added, cannot track times");
220 if (cls >= class_times_.size())
223 timeval *t = (timeval *)malloc(
sizeof(timeval));
224 gettimeofday(t, NULL);
226 if (cls < class_times_.size()) {
227 class_times_[cls].push_back(t);
229 if (class_times_.size() == 0) {
230 throw Exception(
"No classes have been added, cannot track times");
245 if (cls >= class_times_.size())
249 gettimeofday(&t2, NULL);
251 timeval *t1 = class_times_[cls].back();
253 long sec = t2.tv_sec - t1->tv_sec;
254 long usec = t2.tv_usec - t1->tv_usec;
272 if (cls >= class_times_.size())
275 free(class_times_[cls].back());
276 class_times_[cls].pop_back();
280TimeTracker::average_and_deviation(vector<struct timeval *> &values,
281 double & average_sec,
283 double & deviation_sec,
284 double & deviation_ms)
286 vector<struct timeval *>::iterator tit;
288 average_sec = average_ms = deviation_sec = deviation_ms = 0.f;
290 for (tit = values.begin(); tit != values.end(); ++tit) {
291 average_sec += float((*tit)->tv_sec);
292 average_sec += (*tit)->tv_usec / 1000000.f;
294 average_sec /= values.size();
296 for (tit = values.begin(); tit != values.end(); ++tit) {
297 deviation_sec += fabs((*tit)->tv_sec + ((*tit)->tv_usec / 1000000.f) - average_sec);
299 deviation_sec /= values.size();
301 average_ms = average_sec * 1000.f;
302 deviation_ms = deviation_sec * 1000.f;
309 if (!times_.empty()) {
312 long diff_sec_start = 0;
313 long diff_usec_start = 0;
314 long diff_sec_last = 0;
315 long diff_usec_last = 0;
316 float diff_msec_start = 0.0;
317 float diff_msec_last = 0.0;
318 time_t last_sec = start_time.tv_sec;
319 suseconds_t last_usec = start_time.tv_usec;
320 char time_string[26];
322 ctime_r(&(start_time.tv_sec), time_string);
323 for (j = 26; j > 0; --j) {
324 if (time_string[j] ==
'\n') {
330 cout << endl <<
"TimeTracker stats - individual times";
331 if (tracker_comment_.empty()) {
332 cout <<
" (" << tracker_comment_ <<
")";
335 <<
"==================================================================" << endl
336 <<
"Initialized: " << time_string <<
" (" << start_time.tv_sec <<
")" << endl
339 for (time_it_ = times_.begin(); time_it_ != times_.end(); ++time_it_) {
341 sprintf(tmp,
"%3u.", i + 1);
343 if (comments_.count(i) > 0) {
344 cout <<
" (" << comments_[i] <<
")";
348 diff_sec_start = (*time_it_)->tv_sec - start_time.tv_sec;
349 diff_usec_start = (*time_it_)->tv_usec - start_time.tv_usec;
350 if (diff_usec_start < 0) {
352 diff_usec_start = 1000000 + diff_usec_start;
354 diff_msec_start = diff_usec_start / 1000.f;
356 diff_sec_last = (*time_it_)->tv_sec - last_sec;
357 diff_usec_last = (*time_it_)->tv_usec - last_usec;
358 if (diff_usec_last < 0) {
360 diff_usec_last = 1000000 + diff_usec_last;
362 diff_msec_last = diff_usec_last / 1000.f;
364 last_sec = (*time_it_)->tv_sec;
365 last_usec = (*time_it_)->tv_usec;
367 ctime_r(&(*time_it_)->tv_sec, time_string);
368 for (j = 26; j > 0; --j) {
369 if (time_string[j] ==
'\n') {
374 cout << time_string <<
" (" << (*time_it_)->tv_sec <<
")" << endl;
375 cout <<
"Diff to start: " << diff_sec_start <<
" sec and " << diff_usec_start
376 <<
" usec (which are " << diff_msec_start <<
" msec)" << endl;
377 cout <<
"Diff to last: " << diff_sec_last <<
" sec and " << diff_usec_last
378 <<
" usec (which are " << diff_msec_last <<
" msec)" << endl
385 cout << endl <<
"TimeTracker stats - class times";
386 if (!tracker_comment_.empty()) {
387 cout <<
" (" << tracker_comment_ <<
")";
389 cout << endl <<
"==================================================================" << endl;
391 vector<vector<struct timeval *>>::iterator it = class_times_.begin();
392 vector<string>::iterator sit = class_names_.begin();
394 double deviation = 0.f;
395 double average = 0.f;
396 double average_ms = 0.f;
397 double deviation_ms = 0.f;
399 for (; (it != class_times_.end()) && (sit != class_names_.end()); ++it, ++sit) {
403 if (it->size() > 0) {
404 average_and_deviation(*it, average, average_ms, deviation, deviation_ms);
406 cout <<
"Class '" << *sit <<
"'" << endl
407 <<
" avg=" << average <<
" (" << average_ms <<
" ms)" << endl
408 <<
" dev=" << deviation <<
" (" << deviation_ms <<
" ms)" << endl
409 <<
" res=" << it->size() <<
" results" << endl;
411 cout <<
"Class '" << *sit <<
"' has no results." << endl;
429 throw Exception(
"Time log not opened, use other ctor");
431 vector<vector<struct timeval *>>::iterator it = class_times_.begin();
432 vector<string>::iterator sit = class_names_.begin();
434 double deviation = 0.f;
435 double average = 0.f;
436 double average_ms = 0.f;
437 double deviation_ms = 0.f;
440 fprintf(timelog_,
"%u ", ++write_cycle_);
441 for (; (it != class_times_.end()) && (sit != class_names_.end()); ++it, ++sit) {
445 average_and_deviation(*it, average, average_ms, deviation, deviation_ms);
448 fprintf(timelog_,
"%lf %lf %lf %lf %lf ", average, average_ms, avgsum, deviation, deviation_ms);
450 fprintf(timelog_,
"\n");
File could not be opened.
Base class for exceptions in Fawkes.
~ScopedClassItemTracker()
Destructor.
ScopedClassItemTracker(TimeTracker &tt, unsigned int cls)
Constructor.
void print_to_stdout()
Print results to stdout.
void print_to_file()
Print data to file suitable for gnuplot.
TimeTracker(const char *filename, bool add_default_class=false)
Constructor for file logging.
unsigned int add_class(std::string name)
Add a new class.
void reset(std::string comment="")
Reset times.
void ping_end(unsigned int cls)
End of given class task.
void remove_class(unsigned int cls)
Remove a class.
void ping(unsigned int cls)
Ping class.
void ping_abort(unsigned int cls)
End of given class task without recording.
void ping_start(unsigned int cls)
Start of given class task.
~TimeTracker()
Destructor.
static const unsigned int DEFAULT_CLASS
The default tracking class.
Fawkes library namespace.