Added profiler per thread logging.

This commit is contained in:
harry 2023-05-13 20:26:56 -04:00
parent 58b87387eb
commit 7573f1b7dc
6 changed files with 165 additions and 36 deletions

View File

@ -2580,6 +2580,7 @@ int FCEUD_AviGetFormatOpts( std::vector <std::string> &formatList )
AviRecordDiskThread_t::AviRecordDiskThread_t( QObject *parent ) AviRecordDiskThread_t::AviRecordDiskThread_t( QObject *parent )
: QThread(parent) : QThread(parent)
{ {
setObjectName( QString("AviRecordDiskThread") );
} }
//---------------------------------------------------- //----------------------------------------------------
AviRecordDiskThread_t::~AviRecordDiskThread_t(void) AviRecordDiskThread_t::~AviRecordDiskThread_t(void)

View File

@ -125,6 +125,13 @@ consoleWin_t::consoleWin_t(QWidget *parent)
printf("Running on Platform: %s\n", QGuiApplication::platformName().toStdString().c_str() ); printf("Running on Platform: %s\n", QGuiApplication::platformName().toStdString().c_str() );
QThread *thread = QThread::currentThread();
if (thread)
{
thread->setObjectName( QString("MainThread") );
}
QApplication::setStyle( new fceuStyle() ); QApplication::setStyle( new fceuStyle() );
initHotKeys(); initHotKeys();
@ -4604,6 +4611,9 @@ void consoleWin_t::updatePeriodic(void)
updateCounter++; updateCounter++;
#ifdef __FCEU_PROFILER_ENABLE__
FCEU_profiler_log_thread_activity();
#endif
return; return;
} }
@ -4614,6 +4624,7 @@ emulatorThread_t::emulatorThread_t( QObject *parent )
pself = 0; pself = 0;
#endif #endif
setObjectName( QString("EmulationThread") );
} }
#if defined(__linux__) #if defined(__linux__)

View File

@ -2507,6 +2507,7 @@ void QTraceLogView::paintEvent(QPaintEvent *event)
TraceLogDiskThread_t::TraceLogDiskThread_t( QObject *parent ) TraceLogDiskThread_t::TraceLogDiskThread_t( QObject *parent )
: QThread(parent) : QThread(parent)
{ {
setObjectName( QString("TraceLogDiskThread") );
} }
//---------------------------------------------------- //----------------------------------------------------
TraceLogDiskThread_t::~TraceLogDiskThread_t(void) TraceLogDiskThread_t::~TraceLogDiskThread_t(void)

View File

@ -53,6 +53,7 @@
#include "../../cheat.h" #include "../../cheat.h"
#include "../../movie.h" #include "../../movie.h"
#include "../../state.h" #include "../../state.h"
#include "../../profiler.h"
#include "../../version.h" #include "../../version.h"
#ifdef _S9XLUA_H #ifdef _S9XLUA_H
@ -1465,6 +1466,9 @@ int fceuWrapperUpdate( void )
emulatorHasMutex = 0; emulatorHasMutex = 0;
#ifdef __FCEU_PROFILER_ENABLE__
FCEU_profiler_log_thread_activity();
#endif
while ( SpeedThrottle() ) while ( SpeedThrottle() )
{ {
// Input device processing is in main thread // Input device processing is in main thread
@ -1478,6 +1482,9 @@ int fceuWrapperUpdate( void )
emulatorHasMutex = 0; emulatorHasMutex = 0;
#ifdef __FCEU_PROFILER_ENABLE__
FCEU_profiler_log_thread_activity();
#endif
msleep( 100 ); msleep( 100 );
} }
return 0; return 0;

View File

@ -23,6 +23,10 @@
#include <stdio.h> #include <stdio.h>
#ifdef __QT_DRIVER__
#include <QThread>
#endif
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__) #if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
#include <unistd.h> #include <unistd.h>
#endif #endif
@ -37,6 +41,7 @@
namespace FCEU namespace FCEU
{ {
static thread_local profileExecVector execList;
static thread_local profilerFuncMap threadProfileMap; static thread_local profilerFuncMap threadProfileMap;
FILE *profilerManager::pLog = nullptr; FILE *profilerManager::pLog = nullptr;
@ -64,10 +69,8 @@ void timeStampRecord::readNew(void)
{ {
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__) #if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
clock_gettime( CLOCK_REALTIME, &ts ); clock_gettime( CLOCK_REALTIME, &ts );
#elif defined(WIN32)
QueryPerformanceCounter((LARGE_INTEGER*)&ts);
#else #else
ts = 0; QueryPerformanceCounter((LARGE_INTEGER*)&ts);
#endif #endif
tsc = rdtsc(); tsc = rdtsc();
} }
@ -121,16 +124,19 @@ funcProfileRecord::funcProfileRecord(const char *fileNameStringLiteral,
: fileLineNum(fileLineNumber), fileName(fileNameStringLiteral), : fileLineNum(fileLineNumber), fileName(fileNameStringLiteral),
funcName(funcNameStringLiteral), comment(commentStringLiteral) funcName(funcNameStringLiteral), comment(commentStringLiteral)
{ {
min.zero(); min.fromSeconds(9);
max.zero(); max.zero();
sum.zero(); sum.zero();
numCalls = 0; numCalls = 0;
recursionCount = 0; recursionCount = 0;
threadProfileMap.addRecord( fileNameStringLiteral, fileLineNumber,
funcNameStringLiteral, commentStringLiteral, this);
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
void funcProfileRecord::reset(void) void funcProfileRecord::reset(void)
{ {
min.zero(); min.fromSeconds(9);
max.zero(); max.zero();
sum.zero(); sum.zero();
numCalls = 0; numCalls = 0;
@ -149,20 +155,9 @@ double funcProfileRecord::average(void)
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
//---- Profile Scoped Function Class //---- Profile Scoped Function Class
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
profileFuncScoped::profileFuncScoped(const char *fileNameStringLiteral, profileFuncScoped::profileFuncScoped( funcProfileRecord *recordIn )
const int fileLineNumber,
const char *funcNameStringLiteral,
const char *commentStringLiteral)
{ {
rec = nullptr; rec = recordIn;
//if (threadProfileMap == nullptr)
//{
// threadProfileMap = new profilerFuncMap();
//}
rec = threadProfileMap.findRecord( fileNameStringLiteral, fileLineNumber,
funcNameStringLiteral, commentStringLiteral, true);
if (rec) if (rec)
{ {
@ -181,17 +176,70 @@ profileFuncScoped::~profileFuncScoped(void)
ts.readNew(); ts.readNew();
dt = ts - start; dt = ts - start;
rec->last = dt;
rec->sum += dt; rec->sum += dt;
if (dt < rec->min) rec->min = dt; if (dt < rec->min) rec->min = dt;
if (dt > rec->max) rec->max = dt; if (dt > rec->max) rec->max = dt;
rec->recursionCount--; rec->recursionCount--;
//printf("%s: %u %f %f %f %f\n", rec->funcName, rec->numCalls, dt.toSeconds(), rec->average(), rec->min.toSeconds(), rec->max.toSeconds()); execList._vec.push_back(*rec);
threadProfileMap.popStack(rec); threadProfileMap.popStack(rec);
} }
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
//---- Profile Execution Vector
//-------------------------------------------------------------------------
profileExecVector::profileExecVector(void)
{
_vec.reserve( 10000 );
char threadName[128];
char fileName[256];
strcpy( threadName, "MainThread");
#ifdef __QT_DRIVER__
QThread *thread = QThread::currentThread();
if (thread)
{
//printf("Thread: %s\n", thread->objectName().toStdString().c_str());
strcpy( threadName, thread->objectName().toStdString().c_str());
}
#endif
sprintf( fileName, "fceux-profile-%s.log", threadName);
logFp = ::fopen(fileName, "w");
if (logFp == nullptr)
{
printf("Error: Failed to create profiler logfile: %s\n", fileName);
}
}
//-------------------------------------------------------------------------
profileExecVector::~profileExecVector(void)
{
if (logFp)
{
::fclose(logFp);
}
}
//-------------------------------------------------------------------------
void profileExecVector::update(void)
{
size_t n = _vec.size();
for (size_t i=0; i<n; i++)
{
funcProfileRecord &rec = _vec[i];
fprintf( logFp, "%s: %u %f %f %f %f\n", rec.funcName, rec.numCalls, rec.last.toSeconds(), rec.average(), rec.min.toSeconds(), rec.max.toSeconds());
}
_vec.clear();
}
//-------------------------------------------------------------------------
//---- Profile Function Record Map //---- Profile Function Record Map
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
profilerFuncMap::profilerFuncMap(void) profilerFuncMap::profilerFuncMap(void)
@ -207,15 +255,15 @@ profilerFuncMap::~profilerFuncMap(void)
//printf("profilerFuncMap Destructor: %p\n", this); //printf("profilerFuncMap Destructor: %p\n", this);
pMgr.removeThreadProfiler(this); pMgr.removeThreadProfiler(this);
{ //{
autoScopedLock aLock(_mapMtx); // autoScopedLock aLock(_mapMtx);
for (auto it = _map.begin(); it != _map.end(); it++) // for (auto it = _map.begin(); it != _map.end(); it++)
{ // {
delete it->second; // delete it->second;
} // }
_map.clear(); // _map.clear();
} //}
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
void profilerFuncMap::pushStack(funcProfileRecord *rec) void profilerFuncMap::pushStack(funcProfileRecord *rec)
@ -228,6 +276,26 @@ void profilerFuncMap::popStack(funcProfileRecord *rec)
stack.pop_back(); stack.pop_back();
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
int profilerFuncMap::addRecord(const char *fileNameStringLiteral,
const int fileLineNumber,
const char *funcNameStringLiteral,
const char *commentStringLiteral,
funcProfileRecord *rec )
{
autoScopedLock aLock(_mapMtx);
char lineString[64];
sprintf( lineString, ":%i", fileLineNumber);
std::string fname(fileNameStringLiteral);
fname.append( lineString );
_map[fname] = rec;
return 0;
}
//-------------------------------------------------------------------------
funcProfileRecord *profilerFuncMap::findRecord(const char *fileNameStringLiteral, funcProfileRecord *profilerFuncMap::findRecord(const char *fileNameStringLiteral,
const int fileLineNumber, const int fileLineNumber,
const char *funcNameStringLiteral, const char *funcNameStringLiteral,
@ -363,6 +431,12 @@ int profilerManager::removeThreadProfiler( profilerFuncMap *m, bool shouldDestro
return result; return result;
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// } // namespace FCEU
//-------------------------------------------------------------------------
int FCEU_profiler_log_thread_activity(void)
{
FCEU::execList.update();
return 0;
} }
#endif // __FCEU_PROFILER_ENABLE__ #endif // __FCEU_PROFILER_ENABLE__

View File

@ -32,6 +32,7 @@
*/ */
#ifdef __FCEU_PROFILER_ENABLE__ #ifdef __FCEU_PROFILER_ENABLE__
#include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include <vector> #include <vector>
@ -123,7 +124,7 @@ namespace FCEU
} }
else if (ts.tv_sec > op.ts.tv_sec) else if (ts.tv_sec > op.ts.tv_sec)
{ {
res = (ts.tv_sec > op.ts.tv_sec); res = true;
} }
return res; return res;
} }
@ -135,9 +136,9 @@ namespace FCEU
{ {
res = (ts.tv_nsec < op.ts.tv_nsec); res = (ts.tv_nsec < op.ts.tv_nsec);
} }
else if (ts.tv_sec > op.ts.tv_sec) else if (ts.tv_sec < op.ts.tv_sec)
{ {
res = (ts.tv_sec < op.ts.tv_sec); res = true;
} }
return res; return res;
} }
@ -149,6 +150,13 @@ namespace FCEU
tsc = 0; tsc = 0;
} }
void fromSeconds(unsigned int sec)
{
ts.tv_sec = sec;
ts.tv_nsec = 0;
tsc = 0;
}
double toSeconds(void) double toSeconds(void)
{ {
double sec = static_cast<double>(ts.tv_sec) + ( static_cast<double>(ts.tv_nsec) * 1.0e-9 ); double sec = static_cast<double>(ts.tv_sec) + ( static_cast<double>(ts.tv_nsec) * 1.0e-9 );
@ -213,6 +221,12 @@ namespace FCEU
tsc = 0; tsc = 0;
} }
void fromSeconds(unsigned int sec)
{
ts = sec * qpcFreq;
tsc = 0;
}
double toSeconds(void) double toSeconds(void)
{ {
double sec = static_cast<double>(ts) / static_cast<double>(qpcFreq); double sec = static_cast<double>(ts) / static_cast<double>(qpcFreq);
@ -235,6 +249,7 @@ namespace FCEU
timeStampRecord min; timeStampRecord min;
timeStampRecord max; timeStampRecord max;
timeStampRecord sum; timeStampRecord sum;
timeStampRecord last;
unsigned int numCalls; unsigned int numCalls;
unsigned int recursionCount; unsigned int recursionCount;
@ -253,20 +268,35 @@ namespace FCEU
funcProfileRecord *rec; funcProfileRecord *rec;
timeStampRecord start; timeStampRecord start;
profileFuncScoped(const char *fileNameStringLiteral, profileFuncScoped( funcProfileRecord *recordIn );
const int fileLineNumber,
const char *funcNameStringLiteral,
const char *commentStringLiteral);
~profileFuncScoped(void); ~profileFuncScoped(void);
}; };
struct profileExecVector
{
profileExecVector(void);
~profileExecVector(void);
void update(void);
std::vector <funcProfileRecord> _vec;
FILE *logFp;
};
class profilerFuncMap class profilerFuncMap
{ {
public: public:
profilerFuncMap(); profilerFuncMap();
~profilerFuncMap(); ~profilerFuncMap();
int addRecord(const char *fileNameStringLiteral,
const int fileLineNumber,
const char *funcNameStringLiteral,
const char *commentStringLiteral,
funcProfileRecord *rec );
funcProfileRecord *findRecord(const char *fileNameStringLiteral, funcProfileRecord *findRecord(const char *fileNameStringLiteral,
const int fileLineNumber, const int fileLineNumber,
const char *funcNameStringLiteral, const char *funcNameStringLiteral,
@ -312,7 +342,12 @@ namespace FCEU
#define __FCEU_PROFILE_FUNC_NAME__ __func__ #define __FCEU_PROFILE_FUNC_NAME__ __func__
#endif #endif
#define FCEU_PROFILE_FUNC(id, comment) FCEU::profileFuncScoped id( __FILE__, __LINE__, __FCEU_PROFILE_FUNC_NAME__, comment ) #define FCEU_PROFILE_FUNC(id, comment) \
static thread_local FCEU::funcProfileRecord id( __FILE__, __LINE__, __FCEU_PROFILE_FUNC_NAME__, comment ); \
FCEU::profileFuncScoped id ## _unique_scope( &id )
int FCEU_profiler_log_thread_activity(void);
#else // __FCEU_PROFILER_ENABLE__ not defined #else // __FCEU_PROFILER_ENABLE__ not defined