MercuryTimer.cpp

Go to the documentation of this file.
00001 #include "MercuryTimer.h"
00002 #include "MercuryLog.h"
00003 #include "MercuryUtil.h"
00004 
00005 #ifndef WIN32
00006 #include <sys/time.h>
00007 #else
00008 #include <windows.h>
00009 #endif
00010 
00011 #define RESOLUTION 1000000
00012 
00013 MercuryTimer::MercuryTimer()
00014 {
00015     m_pTime = 0;
00016     m_paused = false;
00017     Touch();
00018 }
00019 
00020 MercuryTimer::~MercuryTimer()
00021 {
00022 }
00023 
00024 double MercuryTimer::Peek()
00025 {
00026     return (double(m_secs) + (double(m_usecs) / RESOLUTION)) - m_pTime;
00027 }
00028 
00029 double MercuryTimer::Age()
00030 {
00031     MercuryTimer current;
00032     if (!m_paused)
00033         return (current - *this).Peek();
00034     else
00035     {
00036         m_pTime += (current - *this).Peek();
00037         return 0;
00038     }
00039 }
00040 
00041 void MercuryTimer::Touch()
00042 {
00043     uint64_t usecs = GetTimeMicroseconds();
00044     //We should probably check for clock wraparound
00045 
00046     m_secs = unsigned(usecs / RESOLUTION);
00047     m_usecs = unsigned(usecs % RESOLUTION);
00048 }
00049 
00050 #ifndef WIN32
00051 int64_t GetMicrosecondsSinceEpoch()
00052 {
00053     #if !defined (_EE)
00054         struct timeval tv;
00055         gettimeofday( &tv, 0 );
00056     
00057         return int64_t(tv.tv_sec) * RESOLUTION + int64_t(tv.tv_usec);
00058     #else
00059         return 0;
00060     #endif
00061 }
00062 #endif
00063 
00064 MercuryTimer MercuryTimer::operator-(const MercuryTimer& t)
00065 {
00066     MercuryTimer tmp;
00067     tmp.m_secs = m_secs - t.m_secs;
00068     tmp.m_usecs = m_usecs - t.m_usecs;
00069 
00070     if (tmp.m_usecs < 0)
00071     {
00072         tmp.m_secs--;
00073         tmp.m_usecs += RESOLUTION;
00074     }
00075 
00076     return tmp;
00077 }
00078 
00079 MercuryTimer MercuryTimer::operator+(const MercuryTimer& t)
00080 {
00081     MercuryTimer tmp;
00082     tmp.m_secs = m_secs + t.m_secs;
00083     tmp.m_usecs = m_usecs + t.m_usecs;
00084 
00085     if ((tmp.m_usecs/RESOLUTION) >= 1)
00086     {
00087         tmp.m_secs++;
00088         tmp.m_usecs -= RESOLUTION;
00089     }
00090 
00091     return tmp;
00092 }
00093     
00094 void MercuryTimer::operator=(const MercuryTimer& t)
00095 {
00096     m_secs = t.m_secs;
00097     m_usecs = t.m_usecs;
00098 
00099     m_paused = t.m_paused;
00100     m_pTime = t.m_pTime;
00101 }
00102 
00103 uint64_t MercuryTimer::GetTimeMicroseconds()
00104 {
00105 #ifdef WIN32
00106     int64_t t = timeGetTime() * int64_t(1000);
00107     t = FixupTimeIfLooped(t);
00108     t = FixupTimeIfBackwards(t);
00109     return t;
00110 #else
00111     return GetMicrosecondsSinceEpoch();
00112 #endif
00113 }
00114 
00115 
00116 int64_t MercuryTimer::FixupTimeIfLooped( int64_t usecs )
00117 {
00118     static int64_t last = 0;
00119     static int64_t offset_us = 0;
00120 
00121     /* The time has wrapped if the last time was very high and the current time is very low. */
00122     const int64_t i32BitMaxMs = uint64_t(1) << 32;
00123     const int64_t i32BitMaxUs = i32BitMaxMs*1000;
00124     const int64_t one_day = uint64_t(24*60*60)*1000000;
00125     if( last > (i32BitMaxUs-one_day) && usecs < one_day )
00126         offset_us += i32BitMaxUs;
00127 
00128     last = usecs;
00129 
00130     return usecs + offset_us;
00131 }
00132 
00133 int64_t MercuryTimer::FixupTimeIfBackwards( int64_t usecs )
00134 {
00135     static int64_t last = 0;
00136     static int64_t offset_us = 0;
00137 
00138     if( usecs < last )
00139     {
00140         /* The time has moved backwards.  Increase the offset by the amount we moved. */
00141         offset_us += last - usecs;
00142     }
00143 
00144     last = usecs;
00145 
00146     return usecs + offset_us;
00147 }
00148 
00149 MercuryTimerBenchmark BENCHMARK;
00150 
00151 void MercuryTimerBenchmark::Start( const MString & sName )
00152 {
00153     m_mTotals[sName].tTimer.Touch();
00154 }
00155 
00156 void MercuryTimerBenchmark::End( const MString & sName )
00157 {
00158     m_mTotals[sName].fTotalTime += float(m_mTotals[sName].tTimer.Age());
00159     m_mTotals[sName].iTimesRun++;
00160 }
00161 
00162 void MercuryTimerBenchmark::Print( )
00163 {
00164     std::map< MString, BenchPoint >::iterator c;
00165 
00166     LOG.Info( "Name : Times Run : Total Time : Average Time (ms)" );
00167     for( c = m_mTotals.begin(); c != m_mTotals.end(); c++ )
00168     {
00169         //if ( (c->second).iTimesRun <= 0 )
00170         LOG.Info( ssprintf( "%s : %i : %f : %f", (c->first).c_str(), (c->second).iTimesRun, (c->second).fTotalTime, (c->second).fTotalTime/float((c->second).iTimesRun)*1000.0f ) );
00171     }
00172 }
00173 
00174 /*
00175  *Copyright (c) 2001-2003 Chris Danford, Glenn Maynard
00176  * (c) 2005 Joshua Allen
00177  * (c) 2006 Charles Lohr
00178  * All rights reserved.
00179  * 
00180  * Permission is hereby granted, free of charge, to any person obtaining a
00181  * copy of this software and associated documentation files (the
00182  * "Software"), to deal in the Software without restriction, including
00183  * without limitation the rights to use, copy, modify, merge, publish,
00184  * distribute, and/or sell copies of the Software, and to permit persons to
00185  * whom the Software is furnished to do so, provided that the above
00186  * copyright notice(s) and this permission notice appear in all copies of
00187  * the Software and that both the above copyright notice(s) and this
00188  * permission notice appear in supporting documentation.
00189  * 
00190  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00191  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00192  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
00193  * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
00194  * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
00195  * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
00196  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
00197  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00198  * PERFORMANCE OF THIS SOFTWARE.
00199  */

Hosted by SourceForge.net Logo