diff --git a/Sources/Plasma/FeatureLib/pfConsole/pfConsole.cpp b/Sources/Plasma/FeatureLib/pfConsole/pfConsole.cpp index bad5b98a..85eb794b 100644 --- a/Sources/Plasma/FeatureLib/pfConsole/pfConsole.cpp +++ b/Sources/Plasma/FeatureLib/pfConsole/pfConsole.cpp @@ -1024,8 +1024,8 @@ void pfConsole::Draw( plPipeline *p ) plDebugText& drawText = plDebugText::Instance(); - - thisTime = (float)hsTimer::PrecTicksToSecs( hsTimer::GetPrecTickCount() ); + + thisTime = hsTimer::GetSeconds(); if( fMode == kModeHidden && fEffectCounter == 0 ) { diff --git a/Sources/Plasma/FeatureLib/pfConsole/pfDispatchLog.cpp b/Sources/Plasma/FeatureLib/pfConsole/pfDispatchLog.cpp index 23232190..96c0bb9e 100644 --- a/Sources/Plasma/FeatureLib/pfConsole/pfDispatchLog.cpp +++ b/Sources/Plasma/FeatureLib/pfConsole/pfDispatchLog.cpp @@ -52,7 +52,7 @@ static bool DumpSpecificMsgInfo(plMessage* msg, plString& info); plDispatchLog::plDispatchLog() : fLog(nil), - fStartTicks(hsTimer::GetFullTickCount()) + fStartTicks(hsTimer::GetTicks()) { fLog = plStatusLogMgr::GetInstance().CreateStatusLog(20, "Dispatch.log", plStatusLog::kAlignToTop | plStatusLog::kFilledBackground | plStatusLog::kRawTimeStamp); fIncludeTypes.SetSize(plFactory::GetNumClasses()); @@ -130,7 +130,7 @@ void plDispatchLog::DumpMsg(plMessage* msg, int numReceivers, int sendTimeMs, in fLog->AddLine("\n"); } - float sendTime = hsTimer::FullTicksToMs(hsTimer::GetFullTickCount() - fStartTicks); + float sendTime = hsTimer::GetMilliSeconds(hsTimer::GetTicks() - fStartTicks); char indentStr[50]; indent = hsMinimum(indent, sizeof(indentStr)-1); diff --git a/Sources/Plasma/NucleusLib/inc/hsTimer.h b/Sources/Plasma/NucleusLib/inc/hsTimer.h index 0295a76b..02523ce1 100644 --- a/Sources/Plasma/NucleusLib/inc/hsTimer.h +++ b/Sources/Plasma/NucleusLib/inc/hsTimer.h @@ -42,117 +42,139 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #ifndef hsTimer_Defined #define hsTimer_Defined -#include "hsWide.h" +#include class plTimerShare { +private: + typedef std::chrono::high_resolution_clock Clock; + typedef std::chrono::time_point TimePoint; + typedef Clock::duration Duration; + protected: mutable bool fFirstTime; - mutable hsWide fRawTimeZero; + mutable TimePoint fRawTimeZero; mutable bool fResetSmooth; enum { kSmoothBuffLen = 10 }; - double fSmoothBuff[kSmoothBuffLen]; - int fCurrSlot; - - float fSysTimeScale; - double fRealSeconds; - double fSysSeconds; - float fDelSysSeconds; - float fFrameTimeInc; - bool fRunningFrameTime; - float fTimeClampSecs; - float fSmoothingClampSecs; - bool fClamping; - - hsWide* FactorInTimeZero(hsWide* ticks) const; - - double GetSeconds() const; - double GetMilliSeconds() const; - - hsWide* GetRawTicks(hsWide* ticks) const; - - double RawTicksToDSeconds(const hsWide& ticks); - hsWide DSecondsToRawTicks(double secs); - - float GetDelSysSeconds() const { return fDelSysSeconds; } - double GetSysSeconds() const { return fSysSeconds; } - double IncSysSeconds(); + double fSmoothBuff[kSmoothBuffLen]; + int fCurrSlot; + + float fSysTimeScale; + double fRealSeconds; + double fSysSeconds; + float fDelSysSeconds; + float fFrameTimeInc; + bool fRunningFrameTime; + float fTimeClampSecs; + float fSmoothingClampSecs; + bool fClamping; + + + template + T GetSeconds() const + { + typedef std::chrono::duration duration_type; + Duration d = GetRawTicks(); + return std::chrono::duration_cast(d).count(); + } + + template + T GetSeconds(uint64_t ticks) const + { + typedef std::chrono::duration duration_type; + Duration d(ticks); + return std::chrono::duration_cast(d).count(); + } + + template + T GetMilliSeconds() const + { + typedef std::chrono::duration duration_type; + Duration d = GetRawTicks(); + return std::chrono::duration_cast(d).count(); + } + + template + T GetMilliSeconds(uint64_t ticks) const + { + typedef std::chrono::duration duration_type; + Duration d(ticks); + return std::chrono::duration_cast(d).count(); + } + + uint64_t GetTicks() const; + + float GetDelSysSeconds() const { return fDelSysSeconds; } + double GetSysSeconds() const { return fSysSeconds; } + double IncSysSeconds(); + + void SetRealTime(bool realTime); + bool IsRealTime() const { return !fRunningFrameTime; } + + void SetFrameTimeInc(float inc) { fFrameTimeInc = inc; } + + void SetTimeScale(float s) { fSysTimeScale = s; } + float GetTimeScale() const { return fSysTimeScale; } + + void SetTimeClamp(float secs) { fTimeClampSecs = secs; } + void SetSmoothingCap(float secs) { fSmoothingClampSecs = secs; } + float GetTimeClamp() const { return fTimeClampSecs; } + bool IsClamping() const { return fClamping; } - void SetRealTime(bool realTime); - bool IsRealTime() const { return !fRunningFrameTime; } + friend class hsTimer; - void SetFrameTimeInc(float inc) { fFrameTimeInc = inc; } - void SetTimeScale(float s) { fSysTimeScale = s; } - float GetTimeScale() const { return fSysTimeScale; } +private: + Duration GetRawTicks() const; - void SetTimeClamp(float secs) { fTimeClampSecs = secs; } - void SetSmoothingCap(float secs) { fSmoothingClampSecs = secs; } - float GetTimeClamp() const { return fTimeClampSecs; } - bool IsClamping() const { return fClamping; } - friend class hsTimer; public: plTimerShare(); ~plTimerShare(); }; -class hsTimer + +class hsTimer { protected: - static const double fPrecTicksPerSec; - static const hsWide fRawBase; - - static hsWide IInitRawBase(); - static plTimerShare* fTimer; -public: - static bool VerifyRawBase() { return fRawBase == IInitRawBase(); } - static const hsWide& GetRawBase() { return fRawBase; } - static hsWide* GetRawTicks(hsWide* ticks) { return fTimer->GetRawTicks(ticks); } +public: + template + static T GetSeconds() { return fTimer->GetSeconds(); } - static double GetSeconds() { return fTimer->GetSeconds(); } - static double GetMilliSeconds() { return fTimer->GetMilliSeconds(); } + template + static T GetSeconds(uint64_t ticks) { return fTimer->GetSeconds(ticks); } - static double RawTicksToDSeconds(const hsWide& ticks) { return fTimer->RawTicksToDSeconds(ticks); } - static hsWide DSecondsToRawTicks(double secs) { return fTimer->DSecondsToRawTicks(secs); } + template + static T GetMilliSeconds() { return fTimer->GetMilliSeconds(); } - static float GetDelSysSeconds() { return fTimer->GetDelSysSeconds(); } - static double GetSysSeconds() { return fTimer->GetSysSeconds(); } + template + static T GetMilliSeconds(uint64_t ticks) { return fTimer->GetMilliSeconds(ticks); } - static double IncSysSeconds() { return fTimer->IncSysSeconds(); } + static uint64_t GetTicks() { return fTimer->GetTicks(); } - static void SetRealTime(bool realTime) { fTimer->SetRealTime(realTime); } - static bool IsRealTime() { return fTimer->IsRealTime(); } + static float GetDelSysSeconds() { return fTimer->GetDelSysSeconds(); } + static double GetSysSeconds() { return fTimer->GetSysSeconds(); } - static void SetFrameTimeInc(float inc) { fTimer->SetFrameTimeInc(inc); } + static double IncSysSeconds() { return fTimer->IncSysSeconds(); } - static void SetTimeScale(float s) { fTimer->SetTimeScale(s); } - static float GetTimeScale() { return fTimer->GetTimeScale(); } + static void SetRealTime(bool realTime) { fTimer->SetRealTime(realTime); } + static bool IsRealTime() { return fTimer->IsRealTime(); } - static void SetTimeClamp(float secs) { fTimer->SetTimeClamp(secs); } - static void SetTimeSmoothingClamp(float secs) { fTimer->SetSmoothingCap(secs); } - static float GetTimeClamp() { return fTimer->GetTimeClamp(); } - static bool IsClamping() { return fTimer->IsClamping(); } + static void SetFrameTimeInc(float inc) { fTimer->SetFrameTimeInc(inc); } - /////////////////////////// - // Precision timer routines - these are stateless and implemented as statics. - /////////////////////////// - static uint32_t GetPrecTickCount(); - static double GetPrecTicksPerSec(); - static uint32_t PrecSecsToTicks(float secs); - static double PrecTicksToSecs(uint32_t ticks); - static double PrecTicksToHz(uint32_t ticks); + static void SetTimeScale(float s) { fTimer->SetTimeScale(s); } + static float GetTimeScale() { return fTimer->GetTimeScale(); } - // If you need to time something longer than 20 seconds, use this instead of - // the precision timer. It works the same, it just gives you full resolution. - static uint64_t GetFullTickCount(); - static float FullTicksToMs(uint64_t ticks); + static void SetTimeClamp(float secs) { fTimer->SetTimeClamp(secs); } + static void SetTimeSmoothingClamp(float secs) { fTimer->SetSmoothingCap(secs); } + static float GetTimeClamp() { return fTimer->GetTimeClamp(); } + static bool IsClamping() { return fTimer->IsClamping(); } // // Pass GetTheTimer() into other process space, and then call SetTheTimer() on it. diff --git a/Sources/Plasma/NucleusLib/inc/plProfile.h b/Sources/Plasma/NucleusLib/inc/plProfile.h index aae50af6..9dc7cbd0 100644 --- a/Sources/Plasma/NucleusLib/inc/plProfile.h +++ b/Sources/Plasma/NucleusLib/inc/plProfile.h @@ -153,7 +153,7 @@ public: protected: const char* fName; // Name of timer - uint32_t fValue; + uint64_t fValue; uint32_t fAvgCount; uint64_t fAvgTotal; @@ -168,7 +168,7 @@ protected: void IAddAvg(); - void IPrintValue(uint32_t value, char* buf, bool printType); + void IPrintValue(uint64_t value, char* buf, bool printType); public: plProfileBase(); @@ -179,7 +179,7 @@ public: void UpdateAvg(); - uint32_t GetValue(); + uint64_t GetValue(); void PrintValue(char* buf, bool printType=true); void PrintAvg(char* buf, bool printType=true); @@ -230,7 +230,7 @@ public: void Inc(int i = 1) { fValue += i;} void Dec(int i = 1) { fValue -= i;} - void Set(uint32_t value) { fValue = value; } + void Set(uint64_t value) { fValue = value; } // // For multiple timings per frame of the same thing ie. Each particle system @@ -249,4 +249,4 @@ public: void SetLapsActive(bool s) { fLapsActive = s; } }; -#endif // plProfile_h_inc \ No newline at end of file +#endif // plProfile_h_inc diff --git a/Sources/Plasma/NucleusLib/inc/plProfileManager.cpp b/Sources/Plasma/NucleusLib/inc/plProfileManager.cpp index deb78999..1c6f2eea 100644 --- a/Sources/Plasma/NucleusLib/inc/plProfileManager.cpp +++ b/Sources/Plasma/NucleusLib/inc/plProfileManager.cpp @@ -42,136 +42,10 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plProfileManager.h" #include "plProfile.h" #include "hsTimer.h" -#include "hsWindows.h" -static uint32_t gCyclesPerMS = 0; - -#ifdef HS_BUILD_FOR_WIN32 -#define USE_FAST_TIMER -#endif - -#ifdef USE_FAST_TIMER - -#pragma warning (push) -#pragma warning (disable : 4035) // disable no return value warning - -#ifdef _MSC_VER -#define forceinline __forceinline -#else -#define forceinline inline -#endif - -forceinline uint32_t GetPentiumCounter() -{ -#ifdef _MSC_VER - __asm { - xor eax,eax // VC won't realize that eax is modified w/out this - // instruction to modify the val. - // Problem shows up in release mode builds - _emit 0x0F // Pentium high-freq counter to edx;eax - _emit 0x31 // only care about low 32 bits in eax - - xor edx,edx // so VC gets that edx is modified - } -#endif -} - -#pragma warning (pop) - - - -static uint32_t GetProcSpeed() -{ - const char* keypath[] = - { - "HARDWARE", - "DESCRIPTION", - "System", - "CentralProcessor", - "0" - }; - - HKEY hKey = HKEY_LOCAL_MACHINE; - - int numKeys = sizeof(keypath) / sizeof(char*); - for (int i = 0; i < numKeys; i++) - { - HKEY thisKey = NULL; - bool success = (RegOpenKeyEx(hKey, keypath[i], 0, KEY_READ, &thisKey) == ERROR_SUCCESS); - - RegCloseKey(hKey); - hKey = thisKey; - - if (!success) - return 0; - } - - DWORD value=0, size=sizeof(DWORD); - bool success = (RegQueryValueEx(hKey, "~MHz", 0, NULL, (BYTE*)&value, &size) == ERROR_SUCCESS); - RegCloseKey(hKey); - - return value*1000000; -} - -uint32_t GetProcSpeedAlt() -{ - const uint32_t kSamplePeriodMS = 250; - - // Raise priority to avoid interference from other threads. - int priority = GetThreadPriority(GetCurrentThread()); - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - - uint32_t startTicks, endTicks; - uint64_t pcStart, pcEnd; - - // Count number of processor cycles inside the specified interval - QueryPerformanceCounter((LARGE_INTEGER*)&pcStart); - startTicks = plProfileManager::GetTime(); - Sleep(kSamplePeriodMS); - endTicks = plProfileManager::GetTime(); - QueryPerformanceCounter((LARGE_INTEGER*)&pcEnd); - - // Restore thread priority. - SetThreadPriority(GetCurrentThread(), priority); - - // Calculate Rdtsc/PerformanceCounter ratio; - uint32_t numTicks = endTicks - startTicks; - uint64_t pcDiff = pcEnd - pcStart; - - double ratio = double(numTicks) / double(pcDiff); - uint64_t pcFreq; - QueryPerformanceFrequency((LARGE_INTEGER*)&pcFreq); - - // Calculate CPU frequency. - uint64_t cpuFreq = uint64_t(pcFreq * ratio); - - return (uint32_t)cpuFreq; -} - -#define GetProfileTicks() GetPentiumCounter() - -#else - -#define GetProfileTicks() hsTimer::GetPrecTickCount() - -#endif // USE_FAST_TIMER - -#define TicksToMSec(t) (float(t) / float(gCyclesPerMS)) -#define MSecToTicks(t) (float(t) * float(gCyclesPerMS)) - plProfileManager::plProfileManager() : fLastAvgTime(0), fProcessorSpeed(0) { -#ifdef USE_FAST_TIMER - fProcessorSpeed = GetProcSpeed(); - // Registry stuff only works on NT OS's, have to calc it otherwise - if (fProcessorSpeed == 0) - fProcessorSpeed = GetProcSpeedAlt(); - - gCyclesPerMS = fProcessorSpeed / 1000; -#else - gCyclesPerMS = hsTimer::GetPrecTicksPerSec() / 1000; -#endif } plProfileManager::~plProfileManager() @@ -251,9 +125,9 @@ void plProfileManager::EndFrame() } } -uint32_t plProfileManager::GetTime() +uint64_t plProfileManager::GetTime() { - return GetProfileTicks(); + return hsTimer::GetTicks(); } /////////////////////////////////////////////////////////////////////////////// @@ -300,10 +174,10 @@ void plProfileBase::UpdateAvg() } } -uint32_t plProfileBase::GetValue() +uint64_t plProfileBase::GetValue() { if (hsCheckBits(fDisplayFlags, kDisplayTime)) - return (uint32_t)TicksToMSec(fValue); + return hsTimer::GetMilliSeconds(fValue); else return fValue; } @@ -334,7 +208,7 @@ static const char *insertCommas(unsigned int value) return str; } -void plProfileBase::IPrintValue(uint32_t value, char* buf, bool printType) +void plProfileBase::IPrintValue(uint64_t value, char* buf, bool printType) { if (hsCheckBits(fDisplayFlags, kDisplayCount)) { @@ -348,11 +222,11 @@ void plProfileBase::IPrintValue(uint32_t value, char* buf, bool printType) } else if (hsCheckBits(fDisplayFlags, kDisplayFPS)) { - sprintf(buf, "%.2f", 1000.0f / TicksToMSec(value)); + sprintf(buf, "%.2f", 1000.0f / hsTimer::GetMilliSeconds(value)); } else if (hsCheckBits(fDisplayFlags, kDisplayTime)) { - sprintf(buf, "%.2f", TicksToMSec(value)); + sprintf(buf, "%.2f", hsTimer::GetMilliSeconds(value)); if (printType) strcat(buf, " ms"); } @@ -416,7 +290,7 @@ plProfileLaps::LapInfo* plProfileLaps::IFindLap(const char* lapName) return nil; } -void plProfileLaps::BeginLap(uint32_t curValue, const char* name) +void plProfileLaps::BeginLap(uint64_t curValue, const char* name) { LapInfo* lap = IFindLap(name); if (!lap) @@ -432,7 +306,7 @@ void plProfileLaps::BeginLap(uint32_t curValue, const char* name) lap->BeginTiming(curValue); } -void plProfileLaps::EndLap(uint32_t curValue, const char* name) +void plProfileLaps::EndLap(uint64_t curValue, const char* name) { LapInfo* lap = IFindLap(name); @@ -526,12 +400,12 @@ void plProfileVar::IBeginTiming() if( hsCheckBits( fDisplayFlags, kDisplayResetEveryBegin ) ) fValue = 0; - fValue -= GetProfileTicks(); + fValue -= hsTimer::GetTicks(); } void plProfileVar::IEndTiming() { - fValue += GetProfileTicks(); + fValue += hsTimer::GetTicks(); fTimerSamples++; diff --git a/Sources/Plasma/NucleusLib/inc/plProfileManager.h b/Sources/Plasma/NucleusLib/inc/plProfileManager.h index cef7a60d..36858425 100644 --- a/Sources/Plasma/NucleusLib/inc/plProfileManager.h +++ b/Sources/Plasma/NucleusLib/inc/plProfileManager.h @@ -76,7 +76,7 @@ public: uint32_t GetProcessorSpeed() { return fProcessorSpeed; } // Backdoor for hack timers in calculated profiles - static uint32_t GetTime(); + static uint64_t GetTime(); }; class plProfileLaps @@ -91,16 +91,16 @@ protected: LapInfo(const char* name) { fName = name; fDisplayFlags = kDisplayTime; } bool operator<(const LapInfo& rhs) const { return fLastAvg < rhs.fLastAvg; } - void BeginTiming(uint32_t value) { fValue -= value; } - void EndTiming(uint32_t value) { fValue += value; fTimerSamples++; } + void BeginTiming(uint64_t value) { fValue -= value; } + void EndTiming(uint64_t value) { fValue += value; fTimerSamples++; } }; std::vector fLapTimes; LapInfo* IFindLap(const char* lapName); public: - void BeginLap(uint32_t curValue, const char* name); - void EndLap(uint32_t curValue, const char* name); + void BeginLap(uint64_t curValue, const char* name); + void EndLap(uint64_t curValue, const char* name); void BeginFrame(); void EndFrame(); diff --git a/Sources/Plasma/NucleusLib/pnDispatch/plDispatch.cpp b/Sources/Plasma/NucleusLib/pnDispatch/plDispatch.cpp index e865a09b..82b0ece8 100644 --- a/Sources/Plasma/NucleusLib/pnDispatch/plDispatch.cpp +++ b/Sources/Plasma/NucleusLib/pnDispatch/plDispatch.cpp @@ -311,7 +311,7 @@ void plDispatch::IMsgDispatch() static uint64_t startTicks = 0; if (plDispatchLogBase::IsLogging()) - startTicks = hsTimer::GetFullTickCount(); + startTicks = hsTimer::GetTicks(); int i, numReceivers=0; for( i = 0; fMsgCurrent && i < fMsgCurrent->GetNumReceivers(); i++ ) @@ -343,7 +343,7 @@ void plDispatch::IMsgDispatch() } #ifndef PLASMA_EXTERNAL_RELEASE - uint32_t rcvTicks = hsTimer::GetPrecTickCount(); + uint64_t rcvTicks = hsTimer::GetTicks(); // Object could be deleted by this message, so we need to log this stuff now plString keyname = "(unknown)"; @@ -373,9 +373,9 @@ void plDispatch::IMsgDispatch() #ifndef PLASMA_EXTERNAL_RELEASE if (plDispatchLogBase::IsLoggingLong()) { - rcvTicks = hsTimer::GetPrecTickCount() - rcvTicks; + rcvTicks = hsTimer::GetTicks() - rcvTicks; - float rcvTime = (float)(hsTimer::PrecTicksToSecs(rcvTicks) * 1000.f); + float rcvTime = hsTimer::GetMilliSeconds(rcvTicks); // If the receiver takes more than 5 ms to process its message, log it if (rcvTime > 5.f) plDispatchLogBase::GetInstance()->LogLongReceive(keyname.c_str(), className, clonePlayerID, msg, rcvTime); @@ -392,7 +392,7 @@ void plDispatch::IMsgDispatch() // for message logging // if (plDispatchLogBase::IsLogging()) // { -// float sendTime = hsTimer::FullTicksToMs(hsTimer::GetFullTickCount() - startTicks); +// float sendTime = hsTimer::GetMilliSeconds(hsTimer::GetTicks() - startTicks); // // plDispatchLogBase::GetInstance()->DumpMsg(msg, numReceivers, (int)sendTime, responseLevel*2 /* indent */); // if (origTail==fMsgCurrent) diff --git a/Sources/Plasma/NucleusLib/pnNetCli/pnNetCli.h b/Sources/Plasma/NucleusLib/pnNetCli/pnNetCli.h index b15cb434..4d7319b7 100644 --- a/Sources/Plasma/NucleusLib/pnNetCli/pnNetCli.h +++ b/Sources/Plasma/NucleusLib/pnNetCli/pnNetCli.h @@ -193,7 +193,7 @@ How to create a message sender/receiver: static void SendPing (NetCli player) { const uintptr_t msgPing[] = { kMsgPing, - TimeGetMs(), + hsTimer::GetMilliSeconds(), }; NetCliSend(player, msgPing, arrsize(msgPing)); } diff --git a/Sources/Plasma/NucleusLib/pnTimer/hsTimer.cpp b/Sources/Plasma/NucleusLib/pnTimer/hsTimer.cpp index 9619ad69..08710270 100644 --- a/Sources/Plasma/NucleusLib/pnTimer/hsTimer.cpp +++ b/Sources/Plasma/NucleusLib/pnTimer/hsTimer.cpp @@ -41,7 +41,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com *==LICENSE==*/ #include "hsTimer.h" #include "HeadSpin.h" -#include "hsWindows.h" #include "plTweak.h" @@ -69,47 +68,12 @@ plTimerShare::~plTimerShare() { } -double plTimerShare::GetSeconds() const +uint64_t plTimerShare::GetTicks() const { - hsWide ticks; - return hsTimer::GetRawTicks(&ticks)->AsDouble() / hsTimer::GetRawBase().AsDouble(); -} - -double plTimerShare::GetMilliSeconds() const -{ - return GetSeconds() * 1.e3; -} - -hsWide plTimerShare::DSecondsToRawTicks(double secs) -{ - hsWide retVal; - double ticks = secs * hsTimer::GetRawBase().AsDouble(); - double hi = ticks / double(65536) / double(65536); - ticks -= hi; - retVal.fHi = int32_t(hi); - retVal.fLo = int32_t(ticks); - return retVal; -} + plTimerShare::Duration d = plTimerShare::Clock::now().time_since_epoch(); + typedef std::chrono::duration ticks; -double plTimerShare::RawTicksToDSeconds(const hsWide& ticks) -{ - return ticks.AsDouble() / hsTimer::GetRawBase().AsDouble(); -} - - -inline hsWide* plTimerShare::FactorInTimeZero(hsWide* ticks) const -{ - if( fFirstTime ) - { - fFirstTime = false; - fRawTimeZero = *ticks; - ticks->Set(0, 0); - } - else - { - ticks->Sub(&fRawTimeZero); - } - return ticks; + return std::chrono::duration_cast(d).count(); } double plTimerShare::IncSysSeconds() @@ -198,157 +162,39 @@ double plTimerShare::IncSysSeconds() } void plTimerShare::SetRealTime(bool realTime) -{ - fRunningFrameTime = !realTime; - if( realTime ) +{ + fRunningFrameTime = !realTime; + if (realTime) { fRealSeconds = GetSeconds(); } } -#if HS_BUILD_FOR_WIN32 -hsWide* plTimerShare::GetRawTicks(hsWide* ticks) const +plTimerShare::Duration plTimerShare::GetRawTicks() const { - LARGE_INTEGER large; + plTimerShare::TimePoint tp = Clock::now(); - if (::QueryPerformanceCounter(&large)) - { - ticks->Set(large.HighPart, large.LowPart); + if (fFirstTime) + { + fFirstTime = false; + fRawTimeZero = tp; + return plTimerShare::Duration(0); } else { - ticks->Set(0, ::GetTickCount()); + return plTimerShare::Duration(tp - fRawTimeZero); } - - return FactorInTimeZero(ticks); -} - -hsWide hsTimer::IInitRawBase() -{ - hsWide base; - LARGE_INTEGER large; - if (::QueryPerformanceFrequency(&large)) - base.Set(large.HighPart, large.LowPart); - else - base.Set(0, 1000); - - return base; -} - -#elif HS_BUILD_FOR_UNIX - -#include - -#define kMicroSecondsUnit 1000000 -static uint32_t gBaseTime = 0; - -hsWide* plTimerShare::GetRawTicks(hsWide* ticks) const -{ - timeval tv; - - (void)::gettimeofday(&tv, nil); - if (gBaseTime == 0) - gBaseTime = tv.tv_sec; - - ticks->Mul(tv.tv_sec - gBaseTime, kMicroSecondsUnit)->Add(tv.tv_usec); - return ticks; } -hsWide hsTimer::IInitRawBase() -{ - hsWide base; - base.Set(0, kMicroSecondsUnit); - return base; -} -#endif - -// -// hsTimer - thin static interface to plTimerShare. Also keeps a couple of -// constants. // -static plTimerShare staticTimer; -plTimerShare* hsTimer::fTimer = &staticTimer; // until overridden. -const double hsTimer::fPrecTicksPerSec = hsTimer::GetPrecTicksPerSec(); -const hsWide hsTimer::fRawBase = hsTimer::IInitRawBase(); +// hsTimer - thin static interface to plTimerShare. +// +static plTimerShare staticTimer; +plTimerShare* hsTimer::fTimer = &staticTimer; // until overridden. void hsTimer::SetTheTimer(plTimerShare* timer) { fTimer = timer; } - -/////////////////////////// -// Precision timer routines -// These remain as statics -// since they are stateless -// anyway. -/////////////////////////// - -double hsTimer::GetPrecTicksPerSec() -{ -#if HS_BUILD_FOR_WIN32 - LARGE_INTEGER freq; - if( !QueryPerformanceFrequency(&freq) ) - { - return 1000.f; - } - return ((double) freq.LowPart); -#endif - - return 1; -} - -uint32_t hsTimer::GetPrecTickCount() -{ -#if HS_BUILD_FOR_WIN32 - LARGE_INTEGER ti; - if( !QueryPerformanceCounter(&ti) ) - return GetTickCount(); - - return ti.LowPart; -#else - return 1; -#endif -} -uint32_t hsTimer::PrecSecsToTicks(float secs) -{ - return (uint32_t)(((double)secs) * fPrecTicksPerSec); -} -double hsTimer::PrecTicksToSecs(uint32_t ticks) -{ - return ((double)ticks) / fPrecTicksPerSec; -} -double hsTimer::PrecTicksToHz(uint32_t ticks) -{ - return fPrecTicksPerSec / ((double)ticks); -} - -uint64_t hsTimer::GetFullTickCount() -{ -#if HS_BUILD_FOR_WIN32 - LARGE_INTEGER ticks; - QueryPerformanceCounter(&ticks); - return ticks.QuadPart; -#else - return 0; -#endif -} - -float hsTimer::FullTicksToMs(uint64_t ticks) -{ -#ifdef HS_BUILD_FOR_WIN32 - static uint64_t ticksPerTenthMs = 0; - - if (ticksPerTenthMs == 0) - { - LARGE_INTEGER perfFreq; - QueryPerformanceFrequency(&perfFreq); - ticksPerTenthMs = perfFreq.QuadPart / 10000; - } - - return float(ticks / ticksPerTenthMs) / 10.f; -#else - return 0.f; -#endif -} diff --git a/Sources/Plasma/NucleusLib/pnUtils/pnUtTime.cpp b/Sources/Plasma/NucleusLib/pnUtils/pnUtTime.cpp index 9d54580c..8db63da2 100644 --- a/Sources/Plasma/NucleusLib/pnUtils/pnUtTime.cpp +++ b/Sources/Plasma/NucleusLib/pnUtils/pnUtTime.cpp @@ -58,50 +58,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com * *****************************************************************************/ -namespace pnUtilsExe { - -uint32_t TimeGetTickCount () { -#if HS_BUILD_FOR_WIN32 - return GetTickCount(); -#else - struct timeval tv; - if (gettimeofday(&tv, NULL) != 0) - return 0; - - return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); -#endif -} - -/***************************************************************************** -* -* Time adjustment functions -* -* For debug builds, adjust the initial time value so that the high -* bit or the time value itself is about to wrap, to catch application -* bugs that don't handle wrapping or depend on the high bit's value. -* -***/ - -static uint32_t s_adjustment; - -//=========================================================================== -static void InitializeAdjustment () { - ASSERT(!s_adjustment); - uint32_t currTime = TimeGetTickCount(); - uint32_t startBits = (currTime & 0x80) ? 0x7fff0000 : 0xffff0000; - uint32_t startMask = 0xffff0000; - s_adjustment = (((currTime & ~startMask) | startBits) - currTime) | 1; - ASSERT(s_adjustment); -} - -//=========================================================================== -AUTO_INIT_FUNC(AutoInitializeAdjustment) { - if (!s_adjustment) - InitializeAdjustment(); -} - -} using namespace pnUtilsExe; - /***************************************************************************** * @@ -109,37 +65,14 @@ AUTO_INIT_FUNC(AutoInitializeAdjustment) { * ***/ -uint32_t TimeGetSecondsSince2001Utc () { - uint64_t time = TimeGetTime(); - uint32_t seconds = (uint32_t)((time - kTime1601To2001) / kTimeIntervalsPerSecond); - return seconds; -} - -uint64_t TimeGetTime () { -#ifdef HS_BUILD_FOR_WIN32 - uint64_t time; - static_assert(sizeof(uint64_t) == sizeof(FILETIME), "FILETIME is not a uint64"); - GetSystemTimeAsFileTime((FILETIME *) &time); - return time; +uint32_t TimeGetMs () { +#if HS_BUILD_FOR_WIN32 + return GetTickCount(); #else - struct timespec ts; - if (clock_gettime(CLOCK_MONOTONIC, &ts)) + struct timeval tv; + if (gettimeofday(&tv, NULL) != 0) return 0; - long long time = ts.tv_sec * 1000000000LL + ts.tv_nsec; - - return time / 100; -#endif -} - -uint32_t TimeGetMs () { -#ifdef HS_DEBUGGING - // For debug builds, return an adjusted timer value - if (!s_adjustment) - InitializeAdjustment(); - return TimeGetTickCount() + s_adjustment; -#else - // For release builds, just return the operating system's timer - return TimeGetTickCount(); + return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); #endif } diff --git a/Sources/Plasma/NucleusLib/pnUtils/pnUtTime.h b/Sources/Plasma/NucleusLib/pnUtils/pnUtTime.h index 484f7a5d..4aab2e58 100644 --- a/Sources/Plasma/NucleusLib/pnUtils/pnUtTime.h +++ b/Sources/Plasma/NucleusLib/pnUtils/pnUtTime.h @@ -55,24 +55,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com * Time query functions * ***/ - -const uint64_t kTimeIntervalsPerMs = 10000; -const uint64_t kTimeIntervalsPerSecond = 1000 * kTimeIntervalsPerMs; -const uint64_t kTimeIntervalsPerMinute = 60 * kTimeIntervalsPerSecond; -const uint64_t kTimeIntervalsPerHour = 60 * kTimeIntervalsPerMinute; -const uint64_t kTimeIntervalsPerDay = 24 * kTimeIntervalsPerHour; - // millisecond timer; wraps ~49 days uint32_t TimeGetMs (); - -// 100 nanosecond intervals; won't wrap in our lifetimes -uint64_t TimeGetTime (); - -// Seconds elapsed since 00:00:00 January 1, 2001 UTC -uint32_t TimeGetSecondsSince2001Utc (); - - -// These magic numbers taken from Microsoft's "Shared Source CLI implementation" source code. -// http://msdn.microsoft.com/library/en-us/Dndotnet/html/mssharsourcecli.asp -static const uint64_t kTime1601To2001 = 12622780800 * kTimeIntervalsPerSecond; #endif diff --git a/Sources/Plasma/PubUtilLib/plNetGameLib/Pch.h b/Sources/Plasma/PubUtilLib/plNetGameLib/Pch.h index 7509f12b..0e4e0e90 100644 --- a/Sources/Plasma/PubUtilLib/plNetGameLib/Pch.h +++ b/Sources/Plasma/PubUtilLib/plNetGameLib/Pch.h @@ -57,6 +57,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "pnNetCli/pnNetCli.h" #include "plProduct.h" #include "hsThread.h" +#include "hsTimer.h" #define USES_PROTOCOL_CLI2AUTH #define USES_PROTOCOL_CLI2GAME diff --git a/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglAuth.cpp b/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglAuth.cpp index b93b55d5..6da89ab4 100644 --- a/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglAuth.cpp +++ b/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglAuth.cpp @@ -1272,7 +1272,7 @@ static ENetError FixupPlayerName (wchar_t * name) { //=========================================================================== static unsigned GetNonZeroTimeMs () { - if (unsigned ms = TimeGetMs()) + if (unsigned ms = hsTimer::GetMilliSeconds()) return ms; return 1; } @@ -2523,7 +2523,7 @@ bool PingRequestTrans::Recv ( const Auth2Cli_PingReply & reply = *(const Auth2Cli_PingReply *)msg; m_payload.Set(reply.payload, reply.payloadBytes); - m_replyAtMs = TimeGetMs(); + m_replyAtMs = hsTimer::GetMilliSeconds(); m_result = kNetSuccess; m_state = kTransStateComplete; diff --git a/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglFile.cpp b/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglFile.cpp index a808f4ac..3580379f 100644 --- a/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglFile.cpp +++ b/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglFile.cpp @@ -243,7 +243,7 @@ const unsigned kMinValidConnectionMs = 25 * 1000; //=========================================================================== static unsigned GetNonZeroTimeMs () { - if (unsigned ms = TimeGetMs()) + if (unsigned ms = hsTimer::GetMilliSeconds()) return ms; return 1; } @@ -299,7 +299,7 @@ static void UnlinkAndAbandonConn_CS (CliFileConn * conn) { static void NotifyConnSocketConnect (CliFileConn * conn) { conn->TransferRef("Connecting", "Connected"); - conn->connectStartMs = TimeGetMs(); + conn->connectStartMs = hsTimer::GetMilliSeconds(); conn->numFailedConnects = 0; // Make this the active server @@ -372,7 +372,7 @@ static void NotifyConnSocketDisconnect (CliFileConn * conn) { #ifdef SERVER { - if (TimeGetMs() - conn->connectStartMs > kMinValidConnectionMs) + if (hsTimer::GetMilliSeconds() - conn->connectStartMs > kMinValidConnectionMs) conn->reconnectStartMs = 0; else conn->reconnectStartMs = GetNonZeroTimeMs() + kMaxReconnectIntervalMs; @@ -386,7 +386,7 @@ static void NotifyConnSocketDisconnect (CliFileConn * conn) { // less time elapsed then the connection was likely to a server // with an open port but with no notification procedure registered // for this type of communication channel. - if (TimeGetMs() - conn->connectStartMs > kMinValidConnectionMs) { + if (hsTimer::GetMilliSeconds() - conn->connectStartMs > kMinValidConnectionMs) { conn->reconnectStartMs = 0; } else { @@ -400,7 +400,7 @@ static void NotifyConnSocketDisconnect (CliFileConn * conn) { // send us to a new server, therefore attempt a reconnection to the same // address even if the disconnect was immediate. This is safe because the // file server is stateless with respect to clients. - if (TimeGetMs() - conn->connectStartMs <= kMinValidConnectionMs) { + if (hsTimer::GetMilliSeconds() - conn->connectStartMs <= kMinValidConnectionMs) { if (++conn->numImmediateDisconnects < kMaxImmediateDisconnects) conn->reconnectStartMs = GetNonZeroTimeMs() + kMaxReconnectIntervalMs; else @@ -963,7 +963,7 @@ bool ManifestRequestTrans::Recv ( const uint8_t msg[], unsigned bytes ) { - m_timeoutAtMs = TimeGetMs() + NetTransGetTimeoutMs(); // Reset the timeout counter + m_timeoutAtMs = hsTimer::GetMilliSeconds() + NetTransGetTimeoutMs(); // Reset the timeout counter const File2Cli_ManifestReply & reply = *(const File2Cli_ManifestReply *) msg; @@ -1178,7 +1178,7 @@ bool DownloadRequestTrans::Recv ( const uint8_t msg[], unsigned bytes ) { - m_timeoutAtMs = TimeGetMs() + NetTransGetTimeoutMs(); // Reset the timeout counter + m_timeoutAtMs = hsTimer::GetMilliSeconds() + NetTransGetTimeoutMs(); // Reset the timeout counter const File2Cli_FileDownloadReply & reply = *(const File2Cli_FileDownloadReply *) msg; diff --git a/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglGame.cpp b/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglGame.cpp index 49e5d79a..a2f38124 100644 --- a/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglGame.cpp +++ b/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglGame.cpp @@ -167,7 +167,7 @@ static std::atomic s_perf[kNumPerf]; //=========================================================================== static unsigned GetNonZeroTimeMs () { - if (unsigned ms = TimeGetMs()) + if (unsigned ms = hsTimer::GetMilliSeconds()) return ms; return 1; } diff --git a/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglGateKeeper.cpp b/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglGateKeeper.cpp index 91fc7a0c..52a5beee 100644 --- a/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglGateKeeper.cpp +++ b/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglGateKeeper.cpp @@ -200,7 +200,7 @@ static std::atomic s_perf[kNumPerf]; //=========================================================================== static unsigned GetNonZeroTimeMs () { - if (unsigned ms = TimeGetMs()) + if (unsigned ms = hsTimer::GetMilliSeconds()) return ms; return 1; } @@ -812,7 +812,7 @@ bool PingRequestTrans::Recv ( const GateKeeper2Cli_PingReply & reply = *(const GateKeeper2Cli_PingReply *)msg; m_payload.Set(reply.payload, reply.payloadBytes); - m_replyAtMs = TimeGetMs(); + m_replyAtMs = hsTimer::GetMilliSeconds(); m_result = kNetSuccess; m_state = kTransStateComplete; diff --git a/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglTrans.cpp b/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglTrans.cpp index aa611a1d..da63017f 100644 --- a/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglTrans.cpp +++ b/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglTrans.cpp @@ -219,7 +219,7 @@ bool NetTransRecv (unsigned transId, const uint8_t msg[], unsigned bytes) { return true; // transaction was canceled. // Update the timeout time - trans->m_timeoutAtMs = TimeGetMs() + s_timeoutMs; + trans->m_timeoutAtMs = hsTimer::GetMilliSeconds() + s_timeoutMs; bool result = trans->Recv(msg, bytes); @@ -315,7 +315,7 @@ void NetTransUpdate () { // This is the default "next state", trans->Send() can override this trans->m_state = kTransStateWaitServerResponse; // Set timeout time before calling Send(), allowing Send() to change it if it wants to. - trans->m_timeoutAtMs = TimeGetMs() + s_timeoutMs; + trans->m_timeoutAtMs = hsTimer::GetMilliSeconds() + s_timeoutMs; if (!trans->Send()) { // Revert back to current state so that we'll attempt to send again trans->m_state = kTransStateWaitServerConnect; @@ -326,12 +326,12 @@ void NetTransUpdate () { case kTransStateWaitServerResponse: // Check for timeout - if ((int)(TimeGetMs() - trans->m_timeoutAtMs) > 0) { + if ((int)(hsTimer::GetMilliSeconds() - trans->m_timeoutAtMs) > 0) { // Check to see if the transaction wants to "abort" the timeout if (trans->TimedOut()) CancelTrans_CS(trans, kNetErrTimeout); else - trans->m_timeoutAtMs = TimeGetMs() + s_timeoutMs; // Reset the timeout counter + trans->m_timeoutAtMs = hsTimer::GetMilliSeconds() + s_timeoutMs; // Reset the timeout counter } done = true; break; diff --git a/Sources/Plasma/PubUtilLib/plPipeline/plDTProgressMgr.cpp b/Sources/Plasma/PubUtilLib/plPipeline/plDTProgressMgr.cpp index c130625d..26a05313 100644 --- a/Sources/Plasma/PubUtilLib/plPipeline/plDTProgressMgr.cpp +++ b/Sources/Plasma/PubUtilLib/plPipeline/plDTProgressMgr.cpp @@ -153,7 +153,7 @@ void plDTProgressMgr::Draw( plPipeline *p ) if (fActivePlate) { - float currentMs = hsTimer::FullTicksToMs(hsTimer::GetFullTickCount()); + float currentMs = hsTimer::GetMilliSeconds(); if ((currentMs - fLastDraw) > 30) { fCurrentImage++; diff --git a/Sources/Plasma/PubUtilLib/plResMgr/plResManager.cpp b/Sources/Plasma/PubUtilLib/plResMgr/plResManager.cpp index 4892b8e0..ac6d347f 100644 --- a/Sources/Plasma/PubUtilLib/plResMgr/plResManager.cpp +++ b/Sources/Plasma/PubUtilLib/plResMgr/plResManager.cpp @@ -355,7 +355,7 @@ bool plResManager::IReadObject(plKeyImp* pKey, hsStream *stream) uint64_t startTotalTime = totalTime; uint64_t startTime = 0; if (fLogReadTimes) - startTime = hsTimer::GetFullTickCount(); + startTime = hsTimer::GetTicks(); hsKeyedObject* ko = nil; @@ -449,7 +449,7 @@ bool plResManager::IReadObject(plKeyImp* pKey, hsStream *stream) if (fLogReadTimes) { - uint64_t ourTime = hsTimer::GetFullTickCount() - startTime; + uint64_t ourTime = hsTimer::GetTicks() - startTime; uint64_t childTime = totalTime - startTotalTime; ourTime -= childTime; @@ -457,9 +457,9 @@ bool plResManager::IReadObject(plKeyImp* pKey, hsStream *stream) pKey->GetUoid().GetObjectName().c_str(), plFactory::GetNameOfClass(pKey->GetUoid().GetClassType()), pKey->GetDataLen(), - hsTimer::FullTicksToMs(ourTime)); + hsTimer::GetMilliSeconds(ourTime)); - totalTime += (hsTimer::GetFullTickCount() - startTime) - childTime; + totalTime += (hsTimer::GetTicks() - startTime) - childTime; } return (ko != nil); @@ -1132,7 +1132,7 @@ void plResManager::PageInRoom(const plLocation& page, uint16_t objClassToRef, pl { uint64_t readRoomTime = 0; if (fLogReadTimes) - readRoomTime = hsTimer::GetFullTickCount(); + readRoomTime = hsTimer::GetTicks(); plSynchEnabler ps(false); // disable dirty tracking while paging in @@ -1218,11 +1218,11 @@ void plResManager::PageInRoom(const plLocation& page, uint16_t objClassToRef, pl if (fLogReadTimes) { - readRoomTime = hsTimer::GetFullTickCount() - readRoomTime; + readRoomTime = hsTimer::GetTicks() - readRoomTime; plStatusLog::AddLineS("readtimings.log", plStatusLog::kWhite, "----- Reading page %s>%s took %.1f ms", pageNode->GetPageInfo().GetAge().c_str(), pageNode->GetPageInfo().GetPage().c_str(), - hsTimer::FullTicksToMs(readRoomTime)); + hsTimer::GetMilliSeconds(readRoomTime)); } } diff --git a/Sources/Plasma/PubUtilLib/plStatGather/plAutoProfile.cpp b/Sources/Plasma/PubUtilLib/plStatGather/plAutoProfile.cpp index cb6ca038..ee2b8b4d 100644 --- a/Sources/Plasma/PubUtilLib/plStatGather/plAutoProfile.cpp +++ b/Sources/Plasma/PubUtilLib/plStatGather/plAutoProfile.cpp @@ -337,7 +337,7 @@ bool plAutoProfileImp::MsgReceive(plMessage* msg) { if (!ageLoaded->fLoaded) { - fLinkTime = hsTimer::GetFullTickCount(); + fLinkTime = hsTimer::GetTicks(); hsStatusMessage("Age unloaded"); } return true; @@ -348,8 +348,8 @@ bool plAutoProfileImp::MsgReceive(plMessage* msg) { if (fNextAge > 0) { - fLinkTime = hsTimer::GetFullTickCount() - fLinkTime; - float ms = hsTimer::FullTicksToMs(fLinkTime); + fLinkTime = hsTimer::GetTicks() - fLinkTime; + float ms = hsTimer::GetMilliSeconds(fLinkTime); hsStatusMessageF("Age %s finished load, took %.1f ms", fAges[fNextAge-1].c_str(), diff --git a/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.cpp b/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.cpp index 3a4ec3ec..fb955d69 100644 --- a/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.cpp +++ b/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.cpp @@ -729,7 +729,7 @@ static void SaveDirtyNodes () { static const unsigned kSaveUpdateIntervalMs = 250; static const unsigned kMaxBytesPerSaveUpdate = 5 * 1024; static unsigned s_nextSaveMs; - unsigned currTimeMs = TimeGetMs() | 1; + unsigned currTimeMs = hsTimer::GetMilliSeconds() | 1; if (!s_nextSaveMs || signed(s_nextSaveMs - currTimeMs) <= 0) { s_nextSaveMs = (currTimeMs + kSaveUpdateIntervalMs) | 1; unsigned bytesWritten = 0;