Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008 #include <stdio.h>
00009 #include <stdlib.h>
00010 #include <unistd.h>
00011 #include <string.h>
00012 #include <sys/time.h>
00013
00014 #include <map>
00015 #include <vector>
00016 #include <string>
00017 #include <algorithm>
00018
00019 #include "tictoc.hpp"
00020
00021
00022
00023 namespace fovis
00024 {
00025
00026 static int64_t _timestamp_now()
00027 {
00028 struct timeval tv;
00029 gettimeofday (&tv, NULL);
00030 return (int64_t) tv.tv_sec * 1000000 + tv.tv_usec;
00031 }
00032
00033 static bool
00034 _tictoc_t_avgTimeCompare(const tictoc_t* t1, const tictoc_t* t2)
00035 {
00036 if (t1->numCalls < 1)
00037 return 1;
00038 else if (t2->numCalls < 1)
00039 return 0;
00040 else
00041 return (t1->totalT / t1->numCalls) < (t2->totalT / t2->numCalls);
00042 }
00043 static bool
00044 _tictoc_t_totalTimeCompare(const tictoc_t* t1, const tictoc_t* t2)
00045 {
00046 if (t1->numCalls < 1)
00047 return 1;
00048 else if (t2->numCalls < 1)
00049 return 0;
00050 else
00051 return t1->totalT < t2->totalT;
00052 }
00053 static bool
00054 _tictoc_t_maxTimeCompare(const tictoc_t* t1, const tictoc_t* t2)
00055 {
00056 if (t1->numCalls < 1)
00057 return 1;
00058 else if (t2->numCalls < 1)
00059 return 0;
00060 else
00061 return t1->max < t2->max;
00062 }
00063 static bool
00064 _tictoc_t_minTimeCompare(const tictoc_t* t1, const tictoc_t* t2)
00065 {
00066 if (t1->numCalls < 1)
00067 return 1;
00068 else if (t2->numCalls < 1)
00069 return 0;
00070 else
00071 return t1->min > t2->min;
00072 }
00073 static bool
00074 _tictoc_t_emaTimeCompare(const tictoc_t* t1, const tictoc_t* t2)
00075 {
00076 if (t1->numCalls < 1)
00077 return 1;
00078 else if (t2->numCalls < 1)
00079 return 0;
00080 else
00081 return t1->ema < t2->ema;
00082 }
00083
00084 static bool
00085 _tictoc_t_alphCompare(const tictoc_t* t1, const tictoc_t* t2)
00086 {
00087 if (t1->numCalls < 1)
00088 return 1;
00089 else if (t2->numCalls < 1)
00090 return 0;
00091 else
00092 return strcmp(t1->description.c_str(), t2->description.c_str());
00093 }
00094
00095 static int _tictoc_enabled = 1;
00096 static int _tictoc_initialized = 0;
00097 typedef std::map<std::string, tictoc_t> TictocMap;
00098 static TictocMap _tictoc_map;
00099
00100 static void
00101 _initializeTictoc()
00102 {
00103 const char *tmp;
00104 tmp = getenv(FOVIS_TICTOC_ENV);
00105 if (tmp != NULL) {
00106 _tictoc_enabled = 1;
00107 } else {
00108 _tictoc_enabled = 0;
00109 }
00110 }
00111
00112 int64_t
00113 tictoc(const char *description)
00114 {
00115 return tictoc_full(description, .01, NULL);
00116 }
00117
00118 int64_t
00119 tictoc_full(const char *description, double ema_alpha, int64_t * ema)
00120 {
00121 if (!_tictoc_enabled)
00122 return 0;
00123
00124 int64_t ret = 0;
00125
00126 if (!_tictoc_initialized) {
00127 _tictoc_initialized = 1;
00128 _initializeTictoc();
00129 if (!_tictoc_enabled) {
00130 return 0;
00131 }
00132
00133 }
00134
00135 int64_t tictoctime = _timestamp_now();
00136 TictocMap::iterator eiter = _tictoc_map.find(description);
00137 if(eiter == _tictoc_map.end()) {
00138
00139 tictoc_t entry;
00140 entry.flag = 1;
00141 entry.t = tictoctime;
00142 entry.totalT = 0;
00143 entry.numCalls = 0;
00144 entry.max = -1e15;
00145 entry.min = 1e15;
00146 entry.ema = 0;
00147 entry.description = description;
00148 _tictoc_map[description] = entry;
00149 ret = tictoctime;
00150 } else if (eiter->second.flag == 0) {
00151 eiter->second.flag = 1;
00152 eiter->second.t = tictoctime;
00153 ret = tictoctime;
00154 } else {
00155 eiter->second.flag = 0;
00156 int64_t dt = tictoctime - eiter->second.t;
00157 eiter->second.numCalls++;
00158 eiter->second.totalT += dt;
00159 if (dt < eiter->second.min)
00160 eiter->second.min = dt;
00161 if (dt > eiter->second.max)
00162 eiter->second.max = dt;
00163 eiter->second.ema = (1.0 - ema_alpha) * eiter->second.ema + ema_alpha * dt;
00164 if (ema != NULL)
00165 *ema = eiter->second.ema;
00166 ret = dt;
00167 }
00168 return ret;
00169 }
00170
00171 void
00172 tictoc_get_stats(std::vector<tictoc_t> *stats)
00173 {
00174 if (!_tictoc_enabled) {
00175 return;
00176 }
00177 TictocMap::iterator iter = _tictoc_map.begin();
00178 TictocMap::iterator eiter = _tictoc_map.end();
00179 for(; iter != eiter; ++iter) {
00180 stats->push_back(iter->second);
00181 }
00182 }
00183
00184 void
00185 tictoc_print_stats(tictoc_sort_type_t sortType)
00186 {
00187 if (!_tictoc_enabled) {
00188 return;
00189 }
00190 TictocMap::iterator iter = _tictoc_map.begin();
00191 TictocMap::iterator eiter = _tictoc_map.end();
00192 std::vector<const tictoc_t*> entries;
00193 for(; iter != eiter; ++iter) {
00194 entries.push_back(&iter->second);
00195 }
00196
00197 printf("\n--------------------------------------------\n");
00198 printf("tictoc Statistics, sorted by ");
00199 switch (sortType)
00200 {
00201 case TICTOC_AVG:
00202 printf("average time\n");
00203 std::sort(entries.begin(), entries.end(), _tictoc_t_avgTimeCompare);
00204 break;
00205 case TICTOC_MIN:
00206 printf("min time\n");
00207 std::sort(entries.begin(), entries.end(), _tictoc_t_minTimeCompare);
00208 break;
00209 case TICTOC_MAX:
00210 printf("max time\n");
00211 std::sort(entries.begin(), entries.end(), _tictoc_t_maxTimeCompare);
00212 break;
00213 case TICTOC_EMA:
00214 printf("EMA time\n");
00215 std::sort(entries.begin(), entries.end(), _tictoc_t_emaTimeCompare);
00216 break;
00217 case TICTOC_TOTAL:
00218 printf("total time\n");
00219 std::sort(entries.begin(), entries.end(), _tictoc_t_totalTimeCompare);
00220 break;
00221 case TICTOC_ALPHABETICAL:
00222 printf("alphabetically\n");
00223 std::sort(entries.begin(), entries.end(), _tictoc_t_alphCompare);
00224 break;
00225 default:
00226 fprintf(stderr, "WARNING: invalid sort type in tictoc, using AVG\n");
00227 std::sort(entries.begin(), entries.end(), _tictoc_t_avgTimeCompare);
00228 break;
00229 }
00230 printf("--------------------------------------------\n");
00231 for(std::vector<const tictoc_t*>::iterator iter=entries.begin();
00232 iter != entries.end(); ++iter) {
00233 const tictoc_t* tt = *iter;
00234 if (tt->numCalls < 1)
00235 return;
00236 double totalT = (double) tt->totalT / 1.0e6;
00237 double avgT = ((double) tt->totalT / (double) tt->numCalls) / 1.0e6;
00238 double minT = (double) tt->min / 1.0e6;
00239 double maxT = (double) tt->max / 1.0e6;
00240 double emaT = (double) tt->ema / 1.0e6;
00241 printf("%30s: \t numCalls = %d \t totalT=%.2f \t avgT=%.4f \t minT=%.4f \t maxT=%.4f \t emaT=%.4f\n",
00242 tt->description.c_str(), tt->numCalls, totalT, avgT, minT, maxT, emaT);
00243 }
00244 printf("--------------------------------------------\n");
00245 }
00246
00247 }