Main Page | Namespace List | Class Hierarchy | Compound List | File List | Namespace Members | Compound Members | File Members

abktimer.cxx

Go to the documentation of this file.
00001 /**************************************************************************
00002 ***    
00003 *** Copyright (c) 1995-2000 Regents of the University of California,
00004 ***               Andrew E. Caldwell, Andrew B. Kahng and Igor L. Markov
00005 *** Copyright (c) 2000-2004 Regents of the University of Michigan,
00006 ***               Saurabh N. Adya, Jarrod A. Roy and Igor L. Markov
00007 ***
00008 ***  Contact author(s): abk@cs.ucsd.edu, imarkov@umich.edu
00009 ***  Original Affiliation:   UCLA, Computer Science Department,
00010 ***                          Los Angeles, CA 90095-1596 USA
00011 ***
00012 ***  Permission is hereby granted, free of charge, to any person obtaining 
00013 ***  a copy of this software and associated documentation files (the
00014 ***  "Software"), to deal in the Software without restriction, including
00015 ***  without limitation 
00016 ***  the rights to use, copy, modify, merge, publish, distribute, sublicense, 
00017 ***  and/or sell copies of the Software, and to permit persons to whom the 
00018 ***  Software is furnished to do so, subject to the following conditions:
00019 ***
00020 ***  The above copyright notice and this permission notice shall be included
00021 ***  in all copies or substantial portions of the Software.
00022 ***
00023 *** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
00024 *** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
00025 *** OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
00026 *** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
00027 *** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
00028 *** OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
00029 *** THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00030 ***
00031 ***
00032 ***************************************************************************/
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 /*========================================================================
00043   =   Portable Timer Class    (SunOS, Solaris, Linux, NT, '95, DOS )     =
00044   =                                                Igor Markov 06/22/97  =
00045   = ( with the help of the Regents of the University of California ;-)   =
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; //frequency of perf counter
00073         LARGE_INTEGER _reTime1,_reTime2; //values of perf counter at start,stop
00074         HANDLE        _process;
00075         LONGLONG _usTime1,_usTime2; //units of 100 ns (freq irrelevant)
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; // not to give a suspiciously correct reading
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 

Generated on Mon Apr 25 01:09:23 2005 for Parquete by doxygen 1.3.2