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
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #ifdef _MSC_VER
00050 #pragma warning(disable:4786)
00051 #endif
00052
00053
00054 #include <stdio.h>
00055 #include <iomanip>
00056 #include <limits.h>
00057 #include "abkassert.h"
00058 #include "abktimer.h"
00059 #include "abkcpunorm.h"
00060 #ifdef WIN32
00061 #define _X86_
00062 #include <stdarg.h>
00063 #include <windef.h>
00064 #include <winbase.h>
00065 #include <process.h>
00066 #include <stdio.h>
00067 class WinTimes
00068 {
00069 public:
00070 enum WinKind {NOTSET,WINNT,WIN95,WIN98PLUS,UNKNOWN};
00071 private:
00072 LARGE_INTEGER _freq;
00073 LARGE_INTEGER _reTime1,_reTime2;
00074 HANDLE _process;
00075 LONGLONG _usTime1,_usTime2;
00076 LONGLONG _keTime1,_keTime2;
00077 static WinKind _winKind;
00078 static void _setWinKind();
00079 public:
00080 WinTimes();
00081 ~WinTimes(){::CloseHandle(_process);}
00082 inline double getFreq() {return double(_freq.QuadPart);}
00083 inline LONGLONG getRealTime1() {return _reTime1.QuadPart;}
00084 inline LONGLONG getRealTime2() {return _reTime2.QuadPart;}
00085 inline LONGLONG getKerTime1() {return _keTime1;}
00086 inline LONGLONG getKerTime2() {return _keTime2;}
00087 inline LONGLONG getUserTime1() {return _usTime1;}
00088 inline LONGLONG getUserTime2() {return _usTime2;}
00089 void doTimes1();
00090 void doTimes2();
00091
00092
00093 };
00094
00095 WinTimes::WinKind WinTimes::_winKind=WinTimes::NOTSET;
00096
00097 void WinTimes::_setWinKind()
00098 {
00099 if (_winKind != NOTSET)
00100 {
00101 return;
00102 }
00103 OSVERSIONINFO vInfo;
00104 vInfo.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
00105 if (!::GetVersionEx(&vInfo))
00106 {
00107 _winKind = UNKNOWN;
00108 }
00109 else if (vInfo.dwPlatformId==VER_PLATFORM_WIN32_NT)
00110 {
00111 _winKind = WINNT;
00112 }
00113 else if (vInfo.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)
00114 {
00115 if (vInfo.dwMinorVersion>0)
00116 {
00117 _winKind = WIN98PLUS;
00118 }
00119 else
00120 {
00121 _winKind = WIN95;
00122 }
00123 }
00124 else
00125 _winKind = UNKNOWN;
00126 }
00127
00128 WinTimes::WinTimes()
00129 {
00130 _process = ::OpenProcess(PROCESS_QUERY_INFORMATION,
00131 FALSE,
00132 ::_getpid());
00133 int success=::QueryPerformanceFrequency(&_freq);
00134 abkfatal(success,"Unable to find hi-res timer");
00135
00136 }
00137 void WinTimes::doTimes1()
00138 {
00139 FILETIME CreationTime,ExitTime,KernelTime,UserTime;
00140
00141 int success=::QueryPerformanceCounter(&_reTime1);
00142 abkfatal(success,"Can't get time");
00143
00144 _setWinKind();
00145 if (_winKind==WINNT)
00146 {
00147
00148 success=::GetProcessTimes(_process,
00149 &CreationTime,
00150 &ExitTime,
00151 &KernelTime,
00152 &UserTime);
00153 abkfatal(success,"Can't get time");
00154 _usTime1 = ((__int64)UserTime.dwHighDateTime)<<32
00155 |
00156 (__int64)UserTime.dwLowDateTime;
00157
00158 _keTime1 = ((__int64)KernelTime.dwHighDateTime)<<32
00159 |
00160 (__int64)KernelTime.dwLowDateTime;
00161 }
00162
00163 }
00164 void WinTimes::doTimes2()
00165 {
00166 FILETIME CreationTime,ExitTime,KernelTime,UserTime;
00167
00168 int success=::QueryPerformanceCounter(&_reTime2);
00169 abkfatal(success,"Can't get time");
00170
00171 _setWinKind();
00172
00173 if (_winKind==WINNT)
00174 {
00175 success=::GetProcessTimes(_process,
00176 &CreationTime,
00177 &ExitTime,
00178 &KernelTime,
00179 &UserTime);
00180 abkwarn(success,"Can't get time");
00181 _usTime2 = ((__int64)UserTime.dwHighDateTime)<<32
00182 |
00183 (__int64)UserTime.dwLowDateTime;
00184
00185 _keTime2 = ((__int64)KernelTime.dwHighDateTime)<<32
00186 |
00187 (__int64)KernelTime.dwLowDateTime;
00188 }
00189
00190 }
00191 #endif
00192
00193 Timer::Timer(double limitInSec):timeLimit(limitInSec)
00194 {
00195 #ifdef WIN32
00196 _winTimes = new WinTimes;
00197 #endif
00198 status=TIMER_OFF;
00199 start(limitInSec);
00200 }
00201
00202 #ifdef WIN32
00203 Timer::~Timer()
00204 {
00205 delete _winTimes;
00206 }
00207 #endif
00208
00209 void Timer::start(double limitInSec)
00210 {
00211 abkfatal(status == TIMER_OFF, "Can't start timer twice");
00212 status = TIMER_ON;
00213
00214 timeLimit=limitInSec;
00215
00216 #ifndef WIN32
00217 abkfatal(time(&realTime1)!=-1,"Can't get time");
00218 #endif
00219 #if defined(sun) || defined (linux)
00220 abkfatal(getrusage(RUSAGE_SELF,&_ru)!=-1," Can't get time");
00221 UserTime1 = _ru.ru_utime.tv_sec+1e-6*_ru.ru_utime.tv_usec;
00222 SysTime1 = _ru.ru_stime.tv_sec+1e-6*_ru.ru_stime.tv_usec;
00223 #elif defined(WIN32)
00224 _winTimes->doTimes1();
00225 #else
00226 UserTime1=clock();
00227 #endif
00228 }
00229
00230 void Timer::stop()
00231 {
00232 abkfatal(status == TIMER_ON, "Can't stop timer twice!\n");
00233 status=TIMER_OFF;
00234
00235 #ifndef WIN32
00236 abkfatal(time(&realTime2)!=-1,"Can't get time\n");
00237 #endif
00238
00239 #if defined(sun) || defined(linux)
00240 abkfatal(getrusage(RUSAGE_SELF,&_ru)!=-1," Can't get time");
00241 UserTime2 = _ru.ru_utime.tv_sec+1e-6*_ru.ru_utime.tv_usec;
00242 SysTime2 = _ru.ru_stime.tv_sec+1e-6*_ru.ru_stime.tv_usec;
00243 #elif defined(WIN32)
00244 _winTimes->doTimes2();
00245 #else
00246 UserTime2=clock();
00247 #endif
00248 }
00249
00250 void Timer::split()
00251 {
00252 stop();
00253 status=TIMER_SPLIT;
00254 }
00255
00256 void Timer::resume()
00257 {
00258 abkfatal(status==TIMER_SPLIT,"Can''t resume timer unless split!\n");
00259 status=TIMER_ON;
00260 }
00261
00262 double Timer::getUserTime() const
00263 {
00264 abkfatal(status == TIMER_OFF || status==TIMER_SPLIT,
00265 "Have to stop timer to get a reading\n");
00266 #if defined(sun) || defined(linux)
00267 return (UserTime2-UserTime1);
00268 #elif defined(WIN32)
00269 return (_winTimes->getUserTime2() - _winTimes->getUserTime1())*1.0e-7;
00270 #else
00271 if (getRealTime()>(INT_MAX+0.0)/CLOCKS_PER_SEC)
00272 return 0.0;
00273 return ((UserTime2-UserTime1+0.0)/CLOCKS_PER_SEC);
00274 #endif
00275
00276 }
00277
00278 double Timer::getSysTime() const
00279 {
00280 abkfatal(status == TIMER_OFF || status==TIMER_SPLIT,
00281 "Have to stop timer to get a reading\n");
00282 #if defined(sun) || defined(linux)
00283 return (SysTime2-SysTime1);
00284 #elif defined(WIN32)
00285 return (_winTimes->getKerTime2() - _winTimes->getKerTime1())*1.0e-7;
00286 #else
00287 return 0;
00288 #endif
00289 }
00290
00291 double Timer::getCombTime() const
00292 {
00293 abkfatal(status == TIMER_OFF || status==TIMER_SPLIT,
00294 "Have to stop timer to get a reading\n");
00295 #if defined(sun) || defined(linux)
00296 return (UserTime2-UserTime1)+(SysTime2-SysTime1);
00297 #elif defined(WIN32)
00298 return
00299 ( (_winTimes->getUserTime2() - _winTimes->getUserTime1()) +
00300 (_winTimes->getKerTime2() - _winTimes->getKerTime1()) )
00301 *1.0e-7;
00302 #else
00303 return ((UserTime2-UserTime1+0.0)/CLOCKS_PER_SEC);
00304 #endif
00305 }
00306
00307 double Timer::getRealTime() const
00308 {
00309 abkfatal(status == TIMER_OFF || status==TIMER_SPLIT,
00310 "Have to stop timer to get a reading\n");
00311 #ifdef WIN32
00312 return (_winTimes->getRealTime2()-_winTimes->getRealTime1())/
00313 _winTimes->getFreq();
00314 #else
00315 return difftime(realTime2,realTime1);
00316 #endif
00317 }
00318
00319 double Timer::getUnixTime() const
00320 {
00321 time_t utime, zero=0;
00322 abkfatal(time(&utime)!=-1,"Can't get time\n");
00323 return difftime(utime, zero);
00324 }
00325
00326 ostream& operator<<(ostream& os, const Timer& tm)
00327 {
00328 #if defined(sun) || defined(WIN32) || defined(linux)
00329 CPUNormalizer cpunorm;
00330 double userSec=tm.getUserTime(),
00331 normSec=tm.getUserTime() * cpunorm.getNormalizingFactor();
00332 char buffer[20];
00333 if (userSec>0.01)
00334 {
00335 double frac =userSec-floor(userSec);
00336 double delta=frac-0.001*floor(frac*1000.0);
00337 userSec-=delta;
00338 frac =normSec-floor(normSec);
00339 delta=frac-0.001*floor(frac*1000);
00340 normSec-=delta;
00341 }
00342
00343
00344 sprintf(buffer,"%.1e",tm.getSysTime());
00345
00346 os << " " << userSec <<" user,"
00347 << " " << buffer <<" system,"
00348 << " " << tm.getRealTime() <<" real,"
00349 << " " << normSec << " norm'd "
00350 << "sec ";
00351 #else
00352 if (tm.getRealTime()>(INT_MAX+0.0)/CLOCKS_PER_SEC)
00353 os << tm.getRealTime() << " real sec";
00354 else
00355 os << " " << tm.getUserTime() << " user sec, "
00356 << tm.getRealTime() << " real sec";
00357 #endif
00358 return os;
00359 }
00360
00361 #ifdef WIN32
00362 double Timer::getRealTimeOnTheFly()
00363 {
00364 _winTimes->doTimes2();
00365 return (_winTimes->getRealTime2()-_winTimes->getRealTime1())/
00366 _winTimes->getFreq();
00367 }
00368 double Timer::getUserTimeOnTheFly()
00369 {
00370 _winTimes->doTimes2();
00371 return (_winTimes->getUserTime2() - _winTimes->getUserTime1())*1.0e-7;
00372 }
00373 double Timer::getCombTimeOnTheFly()
00374 {
00375 _winTimes->doTimes2();
00376 return
00377 ( (_winTimes->getUserTime2() - _winTimes->getUserTime1()) +
00378 (_winTimes->getKerTime2() - _winTimes->getKerTime1()) )
00379 *1.0e-7;
00380 }
00381
00382 #endif // WIN32
00383