Moved time stamp functions to its own file. Use new common time stamp functions in Qt GUI timing.

This commit is contained in:
harry 2023-05-19 22:31:01 -04:00
parent a20f6f559b
commit e597f6a4a3
8 changed files with 360 additions and 276 deletions

View File

@ -527,6 +527,7 @@ set(SRC_CORE
${CMAKE_CURRENT_SOURCE_DIR}/utils/md5.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utils/memory.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utils/mutex.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utils/timeStamp.cpp
)

View File

@ -58,6 +58,7 @@
#include "../../profiler.h"
#include "../../version.h"
#include "common/os_utils.h"
#include "utils/timeStamp.h"
#ifdef _S9XLUA_H
#include "../../fceulua.h"

View File

@ -22,6 +22,7 @@
#include "Qt/sdl.h"
#include "Qt/throttle.h"
#include "utils/timeStamp.h"
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
#include <time.h>
@ -60,21 +61,22 @@ extern bool turbo;
double getHighPrecTimeStamp(void)
{
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
struct timespec ts;
double t;
clock_gettime( CLOCK_REALTIME, &ts );
if (FCEU::timeStampModuleInitialized())
{
FCEU::timeStampRecord ts;
t = (double)ts.tv_sec + (double)(ts.tv_nsec * 1.0e-9);
#else
double t;
ts.readNew();
t = (double)SDL_GetTicks();
t = t * 1e-3;
#endif
t = ts.toSeconds();
}
else
{
t = (double)SDL_GetTicks();
t = t * 1e-3;
}
return t;
}

View File

@ -27,18 +27,10 @@
#include <QThread>
#endif
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
#include <unistd.h>
#endif
#include "utils/mutex.h"
#include "fceu.h"
#include "profiler.h"
#if defined(WIN32)
#include <windows.h>
#endif
namespace FCEU
{
static thread_local profileExecVector execList;
@ -48,71 +40,6 @@ FILE *profilerManager::pLog = nullptr;
static profilerManager pMgr;
//-------------------------------------------------------------------------
//---- Time Stamp Record
//-------------------------------------------------------------------------
#if defined(WIN32)
uint64_t timeStampRecord::qpcFreq = 0;
#include <intrin.h>
#pragma intrinsic(__rdtsc)
#else
#include <x86intrin.h>
#endif
uint64_t timeStampRecord::tscFreq = 0;
static uint64_t rdtsc()
{
return __rdtsc();
}
void timeStampRecord::readNew(void)
{
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
clock_gettime( CLOCK_REALTIME, &ts );
#else
QueryPerformanceCounter((LARGE_INTEGER*)&ts);
#endif
tsc = rdtsc();
}
static void calibrateTSC(void)
{
constexpr int numSamples = 1;
timeStampRecord t1, t2, td;
uint64_t td_sum = 0;
double td_avg;
#if defined(WIN32)
if (QueryPerformanceFrequency((LARGE_INTEGER*)&timeStampRecord::qpcFreq) == 0)
{
printf("QueryPerformanceFrequency FAILED!\n");
}
#endif
FCEU_printf("Running TSC Calibration: %i sec...\n", numSamples);
for (int i=0; i<numSamples; i++)
{
t1.readNew();
#if defined(WIN32)
Sleep(1000);
#else
sleep(1);
#endif
t2.readNew();
td += t2 - t1;
td_sum = td.tsc;
td_avg = static_cast<double>(td_sum);
timeStampRecord::tscFreq = static_cast<uint64_t>( td_avg / td.toSeconds() );
FCEU_printf("%i Calibration: %f sec TSC:%llu TSC Freq: %f MHz\n", i, td.toSeconds(),
static_cast<unsigned long long>(td.tsc), static_cast<double>(timeStampRecord::tscFreq) * 1.0e-6 );
}
}
//-------------------------------------------------------------------------
//---- Function Profile Record
//-------------------------------------------------------------------------
@ -371,8 +298,6 @@ profilerManager* profilerManager::getInstance(void)
//-------------------------------------------------------------------------
profilerManager::profilerManager(void)
{
calibrateTSC();
//printf("profilerManager Constructor\n");
if (pLog == nullptr)
{

View File

@ -45,200 +45,10 @@
#endif
#include "utils/mutex.h"
#include "utils/timeStamp.h"
namespace FCEU
{
struct timeStampRecord
{
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
struct timespec ts;
uint64_t tsc;
timeStampRecord(void)
{
ts.tv_sec = 0;
ts.tv_nsec = 0;
tsc = 0;
}
timeStampRecord& operator = (const timeStampRecord& in)
{
ts = in.ts;
tsc = in.tsc;
return *this;
}
timeStampRecord& operator += (const timeStampRecord& op)
{
ts.tv_sec += op.ts.tv_sec;
ts.tv_nsec += op.ts.tv_nsec;
if (ts.tv_nsec >= 1000000000)
{
ts.tv_nsec -= 1000000000;
ts.tv_sec++;
}
tsc += op.tsc;
return *this;
}
timeStampRecord operator + (const timeStampRecord& op)
{
timeStampRecord res;
res.ts.tv_sec = ts.tv_sec + op.ts.tv_sec;
res.ts.tv_nsec = ts.tv_nsec + op.ts.tv_nsec;
if (res.ts.tv_nsec >= 1000000000)
{
res.ts.tv_nsec -= 1000000000;
res.ts.tv_sec++;
}
res.tsc = tsc + op.tsc;
return res;
}
timeStampRecord operator - (const timeStampRecord& op)
{
timeStampRecord res;
res.ts.tv_sec = ts.tv_sec - op.ts.tv_sec;
res.ts.tv_nsec = ts.tv_nsec - op.ts.tv_nsec;
if (res.ts.tv_nsec < 0)
{
res.ts.tv_nsec += 1000000000;
res.ts.tv_sec--;
}
res.tsc = tsc - op.tsc;
return res;
}
bool operator > (const timeStampRecord& op)
{
bool res = false;
if (ts.tv_sec == op.ts.tv_sec)
{
res = (ts.tv_nsec > op.ts.tv_nsec);
}
else if (ts.tv_sec > op.ts.tv_sec)
{
res = true;
}
return res;
}
bool operator < (const timeStampRecord& op)
{
bool res = false;
if (ts.tv_sec == op.ts.tv_sec)
{
res = (ts.tv_nsec < op.ts.tv_nsec);
}
else if (ts.tv_sec < op.ts.tv_sec)
{
res = true;
}
return res;
}
void zero(void)
{
ts.tv_sec = 0;
ts.tv_nsec = 0;
tsc = 0;
}
void fromSeconds(unsigned int sec)
{
ts.tv_sec = sec;
ts.tv_nsec = 0;
tsc = 0;
}
double toSeconds(void)
{
double sec = static_cast<double>(ts.tv_sec) + ( static_cast<double>(ts.tv_nsec) * 1.0e-9 );
return sec;
}
#else // WIN32
uint64_t ts;
uint64_t tsc;
timeStampRecord(void)
{
ts = 0;
tsc = 0;
}
timeStampRecord& operator = (const timeStampRecord& in)
{
ts = in.ts;
tsc = in.tsc;
return *this;
}
timeStampRecord& operator += (const timeStampRecord& op)
{
ts += op.ts;
tsc += op.tsc;
return *this;
}
timeStampRecord operator + (const timeStampRecord& op)
{
timeStampRecord res;
res.ts = ts + op.ts;
res.tsc = tsc + op.tsc;
return res;
}
timeStampRecord operator - (const timeStampRecord& op)
{
timeStampRecord res;
res.ts = ts - op.ts;
res.tsc = tsc - op.tsc;
return res;
}
bool operator > (const timeStampRecord& op)
{
return ts > op.ts;
}
bool operator < (const timeStampRecord& op)
{
return ts < op.ts;
}
void zero(void)
{
ts = 0;
tsc = 0;
}
void fromSeconds(unsigned int sec)
{
ts = sec * qpcFreq;
tsc = 0;
}
double toSeconds(void)
{
double sec = static_cast<double>(ts) / static_cast<double>(qpcFreq);
return sec;
}
static uint64_t qpcFreq;
#endif
static uint64_t tscFreq;
void readNew(void);
};
struct funcProfileRecord
{
const int fileLineNum;

112
src/utils/timeStamp.cpp Normal file
View File

@ -0,0 +1,112 @@
// timeStamp.cpp
#include <stdio.h>
#include "timeStamp.h"
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
#include <unistd.h>
#endif
#if defined(WIN32)
#include <windows.h>
#endif
//-------------------------------------------------------------------------
//---- Time Stamp Record
//-------------------------------------------------------------------------
#if defined(WIN32)
uint64_t timeStampRecord::qpcFreq = 0;
#include <intrin.h>
#pragma intrinsic(__rdtsc)
#else
#include <x86intrin.h>
#endif
static uint64_t rdtsc()
{
return __rdtsc();
}
namespace FCEU
{
uint64_t timeStampRecord::tscFreq = 0;
void timeStampRecord::readNew(void)
{
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
clock_gettime( CLOCK_REALTIME, &ts );
#else
QueryPerformanceCounter((LARGE_INTEGER*)&ts);
#endif
tsc = rdtsc();
}
static timeStampRecord cal_t1, cal_t2, cal_td;
class timeStampModule
{
public:
timeStampModule(void)
{
printf("timeStampModuleInit\n");
#if defined(WIN32)
if (QueryPerformanceFrequency((LARGE_INTEGER*)&StampRecord::qpcFreq) == 0)
{
printf("QueryPerformanceFrequency FAILED!\n");
}
#endif
}
};
static timeStampModule module;
bool timeStampModuleInitialized(void)
{
bool initialized = false;
#if defined(WIN32)
initialized = timeStampRecord::qpcFreq != 0;
#else
initialized = true;
#endif
return initialized;
}
void timeStampModuleCalibrate(int numSamples)
{
timeStampRecord t1, t2, td;
uint64_t td_sum = 0;
double td_avg;
#if defined(WIN32)
if (QueryPerformanceFrequency((LARGE_INTEGER*)&timeStampRecord::qpcFreq) == 0)
{
printf("QueryPerformanceFrequency FAILED!\n");
}
#endif
printf("Running TSC Calibration: %i sec...\n", numSamples);
for (int i=0; i<numSamples; i++)
{
t1.readNew();
#if defined(WIN32)
Sleep(1000);
#else
sleep(1);
#endif
t2.readNew();
td += t2 - t1;
td_sum = td.tsc;
td_avg = static_cast<double>(td_sum);
timeStampRecord::tscFreq = static_cast<uint64_t>( td_avg / td.toSeconds() );
printf("%i Calibration: %f sec TSC:%llu TSC Freq: %f MHz\n", i, td.toSeconds(),
static_cast<unsigned long long>(td.tsc), static_cast<double>(timeStampRecord::tscFreq) * 1.0e-6 );
}
}
} // namespace FCEU

231
src/utils/timeStamp.h Normal file
View File

@ -0,0 +1,231 @@
// timeStamp.h
#pragma once
#include <stdint.h>
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
#include <time.h>
#endif
namespace FCEU
{
struct timeStampRecord
{
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
struct timespec ts;
uint64_t tsc;
timeStampRecord(void)
{
ts.tv_sec = 0;
ts.tv_nsec = 0;
tsc = 0;
}
timeStampRecord& operator = (const timeStampRecord& in)
{
ts = in.ts;
tsc = in.tsc;
return *this;
}
timeStampRecord& operator += (const timeStampRecord& op)
{
ts.tv_sec += op.ts.tv_sec;
ts.tv_nsec += op.ts.tv_nsec;
if (ts.tv_nsec >= 1000000000)
{
ts.tv_nsec -= 1000000000;
ts.tv_sec++;
}
tsc += op.tsc;
return *this;
}
timeStampRecord operator + (const timeStampRecord& op)
{
timeStampRecord res;
res.ts.tv_sec = ts.tv_sec + op.ts.tv_sec;
res.ts.tv_nsec = ts.tv_nsec + op.ts.tv_nsec;
if (res.ts.tv_nsec >= 1000000000)
{
res.ts.tv_nsec -= 1000000000;
res.ts.tv_sec++;
}
res.tsc = tsc + op.tsc;
return res;
}
timeStampRecord operator - (const timeStampRecord& op)
{
timeStampRecord res;
res.ts.tv_sec = ts.tv_sec - op.ts.tv_sec;
res.ts.tv_nsec = ts.tv_nsec - op.ts.tv_nsec;
if (res.ts.tv_nsec < 0)
{
res.ts.tv_nsec += 1000000000;
res.ts.tv_sec--;
}
res.tsc = tsc - op.tsc;
return res;
}
bool operator > (const timeStampRecord& op)
{
bool res = false;
if (ts.tv_sec == op.ts.tv_sec)
{
res = (ts.tv_nsec > op.ts.tv_nsec);
}
else if (ts.tv_sec > op.ts.tv_sec)
{
res = true;
}
return res;
}
bool operator < (const timeStampRecord& op)
{
bool res = false;
if (ts.tv_sec == op.ts.tv_sec)
{
res = (ts.tv_nsec < op.ts.tv_nsec);
}
else if (ts.tv_sec < op.ts.tv_sec)
{
res = true;
}
return res;
}
void zero(void)
{
ts.tv_sec = 0;
ts.tv_nsec = 0;
tsc = 0;
}
void fromSeconds(unsigned int sec)
{
ts.tv_sec = sec;
ts.tv_nsec = 0;
tsc = 0;
}
double toSeconds(void)
{
double sec = static_cast<double>(ts.tv_sec) + ( static_cast<double>(ts.tv_nsec) * 1.0e-9 );
return sec;
}
uint64_t toCounts(void)
{
return (ts.tv_sec * 1000000000) + ts.tv_nsec;
}
static uint64_t countFreq(void)
{
return 1000000000;
}
#else // WIN32
uint64_t ts;
uint64_t tsc;
timeStampRecord(void)
{
ts = 0;
tsc = 0;
}
timeStampRecord& operator = (const timeStampRecord& in)
{
ts = in.ts;
tsc = in.tsc;
return *this;
}
timeStampRecord& operator += (const timeStampRecord& op)
{
ts += op.ts;
tsc += op.tsc;
return *this;
}
timeStampRecord operator + (const timeStampRecord& op)
{
timeStampRecord res;
res.ts = ts + op.ts;
res.tsc = tsc + op.tsc;
return res;
}
timeStampRecord operator - (const timeStampRecord& op)
{
timeStampRecord res;
res.ts = ts - op.ts;
res.tsc = tsc - op.tsc;
return res;
}
bool operator > (const timeStampRecord& op)
{
return ts > op.ts;
}
bool operator < (const timeStampRecord& op)
{
return ts < op.ts;
}
void zero(void)
{
ts = 0;
tsc = 0;
}
void fromSeconds(unsigned int sec)
{
ts = sec * qpcFreq;
tsc = 0;
}
double toSeconds(void)
{
double sec = static_cast<double>(ts) / static_cast<double>(qpcFreq);
return sec;
}
uint64_t toCounts(void)
{
return ts;
}
static uint64_t countFreq(void)
{
return qpcFreq;
}
static uint64_t qpcFreq;
#endif
static uint64_t tscFreq;
static bool tscValid(void){ return tscFreq != 0; };
void readNew(void);
};
bool timeStampModuleInitialized(void);
// Call this function to calibrate the estimated TSC frequency
void timeStampModuleCalibrate(int numSamples = 1);
} // namespace FCEU

View File

@ -743,6 +743,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)"</Command>
<ClCompile Include="..\src\utils\md5.cpp" />
<ClCompile Include="..\src\utils\memory.cpp" />
<ClCompile Include="..\src\utils\mutex.cpp" />
<ClCompile Include="..\src\utils\timeStamp.cpp" />
<ClCompile Include="..\src\utils\unzip.cpp" />
<ClCompile Include="..\src\utils\xstring.cpp" />
<ClCompile Include="..\src\lua\src\lapi.c">
@ -1152,6 +1153,7 @@ xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z_64.dll" "$(OutDir)"</Command>
<ClInclude Include="..\src\utils\md5.h" />
<ClInclude Include="..\src\utils\memory.h" />
<ClInclude Include="..\src\utils\mutex.h" />
<ClInclude Include="..\src\utils\timeStamp.h" />
<ClInclude Include="..\src\utils\unzip.h" />
<ClInclude Include="..\src\utils\valuearray.h" />
<ClInclude Include="..\src\utils\xstring.h" />