Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "perf.h"
00036
00037 #include <iostream>
00038
00039 #ifdef WIN32
00040 #include <winsock2.h>
00041 #include <time.h>
00042 #else // WIN32
00043 #include <sys/time.h>
00044 #endif // WIN32
00045
00046 #include "threadsafe/threadsafe_map.h"
00047
00048
00049 #ifdef WIN32
00050
00051 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
00052 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
00053 #else
00054 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
00055 #endif
00056
00057
00058
00059 int
00060 gettimeofday
00061 (
00062 struct timeval *tv,
00063 struct timezone *tz
00064 )
00065 {
00066 ASSERT(tv, "null");
00067 ASSERT(!tz, "do not support timezone");
00068
00069
00070
00071
00072 FILETIME ft;
00073
00074
00075 unsigned __int64 tmpres = 0;
00076
00077 GetSystemTimeAsFileTime(&ft);
00078
00079
00080
00081
00082 tmpres |= ft.dwHighDateTime;
00083 tmpres <<= 32;
00084 tmpres |= ft.dwLowDateTime;
00085
00086
00087 tmpres /= 10;
00088
00089
00090
00091 tmpres -= DELTA_EPOCH_IN_MICROSECS;
00092
00093
00094
00095 tv->tv_sec = (long)(tmpres / 1000000UL);
00096 tv->tv_usec = (long)(tmpres % 1000000UL);
00097
00098
00099
00100 return 0;
00101 }
00102
00103 #endif // WIN32
00104
00105
00106
00107 namespace perf {
00108
00109
00110 struct timer_rec_t {
00111
00112 timer_rec_t(void) throw() {
00113 calls = 0;
00114 total.clear();
00115 }
00116
00117 void update(IN const time_t& delta) throw() {
00118 mlock m(mutex);
00119
00120 calls++;
00121 total.increment(delta);
00122 }
00123
00124
00125 smart_mutex mutex;
00126 long calls;
00127 time_t total;
00128 };
00129
00130 typedef threadsafe_map<std::string, timer_rec_t *> map_timer_t;
00131
00132 typedef std::multimap<double, std::string> map_time_name_t;
00133
00134
00135 static bool s_timersEnabled = true;
00136
00137 static map_timer_t s_timers;
00138
00139
00140
00141
00142
00143
00144
00145
00146 static void *
00147 initializeTimer
00148 (
00149 IN const char * name
00150 )
00151 {
00152 ASSERT(name, "null");
00153
00154 timer_rec_t * tr = NULL;
00155 if (s_timers.lookup(name, tr)) {
00156 ASSERT(tr, "null timer record in map?");
00157 return tr;
00158 }
00159
00160
00161 tr = new timer_rec_t;
00162 ASSERT(tr, "out of memory");
00163
00164
00165 s_timers.insert(name, tr);
00166 return tr;
00167 }
00168
00169
00170
00171 static void
00172 updateTimer
00173 (
00174 IN void * context,
00175 IN const time_t& delta
00176 )
00177 throw()
00178 {
00179 ASSERT(context, "null");
00180
00181 timer_rec_t * tr = (timer_rec_t *) context;
00182
00183
00184 tr->update(delta);
00185 }
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 Timer::Timer
00196 (
00197 IN const char * name
00198 )
00199 {
00200 ASSERT(name, "null timer name?");
00201
00202 if (!s_timersEnabled) {
00203 m_context = 0;
00204 return;
00205 }
00206
00207
00208
00209 m_start_time = getNow();
00210 m_context = initializeTimer(name);
00211 }
00212
00213
00214
00215 Timer::~Timer(void)
00216 {
00217 if (!m_context)
00218 return;
00219
00220 time_t delta = getNow();
00221 delta.decrement(m_start_time);
00222
00223 updateTimer(m_context, delta);
00224 }
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 DebugTimer::DebugTimer(IN const char * msg)
00235 {
00236 m_start_time = getNow();
00237 m_msg = msg;
00238 }
00239
00240
00241 DebugTimer::~DebugTimer(void) throw()
00242 {
00243 time_t now = getNow();
00244 now.decrement(m_start_time);
00245
00246 long seconds = (long) now.getSeconds();
00247 long hours = seconds / 3600;
00248 long minutes = (seconds % 3600) / 60;
00249 DPRINTF("%s: %ld hours %ld minutes %ld seconds",
00250 m_msg.c_str(), hours, minutes, seconds % 60);
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 time_t
00262 getNow
00263 (
00264 void
00265 )
00266 throw()
00267 {
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 time_t t;
00281 struct timeval tv;
00282 ASSERT(!gettimeofday(&tv, NULL), "Failed calling gettimeofday()");
00283 t.set(tv.tv_sec, tv.tv_usec);
00284 return t;
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 }
00303
00304
00305
00306 void
00307 enableTimers
00308 (
00309 IN bool enable
00310 )
00311 throw()
00312 {
00313 s_timersEnabled = enable;
00314
00315 if (enable) {
00316 DPRINTF("Timers enabled");
00317 } else {
00318 DPRINTF("Timers disabled");
00319 }
00320 }
00321
00322
00323
00324 void
00325 getTimingSummary
00326 (
00327 OUT std::string& out
00328 )
00329 {
00330 out = "";
00331
00332 char buffer[1024];
00333
00334
00335 map_time_name_t map;
00336 map_timer_t::iterator_t M;
00337 s_timers.getIterator(M);
00338 std::string name;
00339 timer_rec_t * tr = NULL;
00340 while (s_timers.getNextElement(M, name, tr)) {
00341 ASSERT(tr, "null timer record in timer map?");
00342 map.insert(map_time_name_t::value_type(tr->total.getSeconds(), name));
00343 }
00344
00345
00346 for (map_time_name_t::reverse_iterator i = map.rbegin();
00347 i != map.rend(); ++i) {
00348
00349 const std::string& name = i->second;
00350 timer_rec_t * tr;
00351 ASSERT(s_timers.lookup(name, tr) && tr,
00352 "Missing or invalid record for '%s'", name.c_str());
00353
00354 out += " ";
00355
00356 sprintf(buffer, "%31s", name.c_str());
00357 out += buffer;
00358 out += ": ";
00359
00360 double s = tr->total.getSeconds();
00361 double mpc = 1000.0 * s / tr->calls;
00362
00363 int min = 0;
00364 if (s > 90.0) {
00365 min = int(s / 60.0);
00366 s = s - (60.0 * min);
00367 }
00368
00369 if (min > 0) {
00370 sprintf(buffer,
00371 "%7ld calls, %2d minutes %4.1lf seconds",
00372 tr->calls, min, s);
00373 } else {
00374 sprintf(buffer,
00375 "%7ld calls, %5.2lf seconds", tr->calls, s);
00376 }
00377 out += buffer;
00378
00379 if (mpc < 1000.0) {
00380 sprintf(buffer, ": %6.2lf ms/call", mpc);
00381 out += buffer;
00382 }
00383
00384 out += "\n";
00385 }
00386 }
00387
00388
00389
00390 void
00391 dumpTimingSummary
00392 (
00393 IO std::ostream& stream
00394 )
00395 {
00396 ASSERT(stream.good(), "bad?");
00397
00398 std::string summary;
00399 getTimingSummary(summary);
00400 stream << "Timing Summary:\n";
00401 stream << summary;
00402 stream << "\n";
00403 }
00404
00405
00406
00407 };
00408