Added a separate thread to Qt trace logger whose job is to just write the logged instructions to disk (when disk logging is enabled only). This allows for bottle necks with disk I/O to not slow down the emulation. Also, buffer 4k blocks before writing to disk to make more efficient.

This commit is contained in:
mjbudd77 2021-04-25 22:07:59 -04:00
parent aa5ce14c06
commit f146a7f7f1
4 changed files with 138 additions and 24 deletions

View File

@ -139,7 +139,7 @@ consoleWin_t::consoleWin_t(QWidget *parent)
#else #else
mutex = new QMutex( QMutex::Recursive ); mutex = new QMutex( QMutex::Recursive );
#endif #endif
emulatorThread = new emulatorThread_t(); emulatorThread = new emulatorThread_t(this);
connect(emulatorThread, &QThread::finished, emulatorThread, &QObject::deleteLater); connect(emulatorThread, &QThread::finished, emulatorThread, &QObject::deleteLater);
@ -3370,7 +3370,8 @@ void consoleWin_t::updatePeriodic(void)
return; return;
} }
emulatorThread_t::emulatorThread_t(void) emulatorThread_t::emulatorThread_t( QObject *parent )
: QThread(parent)
{ {
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__) #if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
pself = 0; pself = 0;

View File

@ -36,7 +36,7 @@ class emulatorThread_t : public QThread
void run( void ) override; void run( void ) override;
public: public:
emulatorThread_t(void); emulatorThread_t( QObject *parent = 0 );
void setPriority( QThread::Priority priority ); void setPriority( QThread::Priority priority );

View File

@ -99,6 +99,10 @@ static traceRecord_t *recBuf = NULL;
static int recBufMax = 0; static int recBufMax = 0;
static int recBufHead = 0; static int recBufHead = 0;
static int recBufTail = 0; static int recBufTail = 0;
static traceRecord_t *logBuf = NULL;
static int logBufMax = 1000000;
static int logBufHead = 0;
static int logBufTail = 0;
static FILE *logFile = NULL; static FILE *logFile = NULL;
static bool overrunWarningArmed = true; static bool overrunWarningArmed = true;
static TraceLoggerDialog_t *traceLogWindow = NULL; static TraceLoggerDialog_t *traceLogWindow = NULL;
@ -311,21 +315,23 @@ TraceLoggerDialog_t::TraceLoggerDialog_t(QWidget *parent)
connect(updateTimer, &QTimer::timeout, this, &TraceLoggerDialog_t::updatePeriodic); connect(updateTimer, &QTimer::timeout, this, &TraceLoggerDialog_t::updatePeriodic);
updateTimer->start(10); // 100hz updateTimer->start(50); // 20hz
diskThread = new TraceLogDiskThread_t(this);
} }
//---------------------------------------------------- //----------------------------------------------------
TraceLoggerDialog_t::~TraceLoggerDialog_t(void) TraceLoggerDialog_t::~TraceLoggerDialog_t(void)
{ {
updateTimer->stop(); updateTimer->stop();
traceLogWindow = NULL;
logging = 0; logging = 0;
msleep(1);
diskThread->requestInterruption();
diskThread->quit();
diskThread->wait( 1000 );
traceLogWindow = NULL;
if (logFile)
{
fclose(logFile);
logFile = NULL;
}
printf("Trace Logger Window Deleted\n"); printf("Trace Logger Window Deleted\n");
} }
//---------------------------------------------------- //----------------------------------------------------
@ -366,16 +372,16 @@ void TraceLoggerDialog_t::updatePeriodic(void)
if (logFile && logFileCbox->isChecked()) if (logFile && logFileCbox->isChecked())
{ {
char line[256]; //char line[256];
while (recBufHead != recBufTail) //while (recBufHead != recBufTail)
{ //{
recBuf[recBufTail].convToText(line); // recBuf[recBufTail].convToText(line);
fprintf(logFile, "%s\n", line); // fprintf(logFile, "%s\n", line);
recBufTail = (recBufTail + 1) % recBufMax; // recBufTail = (recBufTail + 1) % recBufMax;
} //}
} }
else else
{ {
@ -427,17 +433,17 @@ void TraceLoggerDialog_t::toggleLoggingOnOff(void)
pushMsgToLogBuffer("Logging Finished"); pushMsgToLogBuffer("Logging Finished");
startStopButton->setText(tr("Start Logging")); startStopButton->setText(tr("Start Logging"));
if (logFile) diskThread->requestInterruption();
{ diskThread->quit();
fclose(logFile); diskThread->wait(1000);
logFile = NULL;
}
} }
else else
{ {
if (logFileCbox->isChecked()) if (logFileCbox->isChecked())
{ {
openLogFile(); openLogFile();
diskThread->start();
msleep(100);
} }
pushMsgToLogBuffer("Log Start"); pushMsgToLogBuffer("Log Start");
startStopButton->setText(tr("Stop Logging")); startStopButton->setText(tr("Stop Logging"));
@ -1026,12 +1032,15 @@ static void pushToLogBuffer(traceRecord_t &rec)
recBuf[recBufHead] = rec; recBuf[recBufHead] = rec;
recBufHead = (recBufHead + 1) % recBufMax; recBufHead = (recBufHead + 1) % recBufMax;
if ( logFile != NULL ) if ( logBuf )
{ {
logBuf[logBufHead] = rec;
logBufHead = (logBufHead + 1) % logBufMax;
if ( overrunWarningArmed ) if ( overrunWarningArmed )
{ // Don't spam with buffer overrun warning messages, { // Don't spam with buffer overrun warning messages,
// we will print once if this happens. // we will print once if this happens.
if (recBufHead == recBufTail) if (logBufHead == logBufTail)
{ {
if ( traceLogWindow ) if ( traceLogWindow )
{ {
@ -2157,3 +2166,88 @@ void QTraceLogView::paintEvent(QPaintEvent *event)
} }
} }
//---------------------------------------------------- //----------------------------------------------------
TraceLogDiskThread_t::TraceLogDiskThread_t( QObject *parent )
: QThread(parent)
{
}
//----------------------------------------------------
TraceLogDiskThread_t::~TraceLogDiskThread_t(void)
{
printf("Disk Thread Cleanup\n");
if (logFile)
{
fclose(logFile);
logFile = NULL;
}
if ( logBuf )
{
free(logBuf);
logBuf = NULL;
}
}
//----------------------------------------------------
void TraceLogDiskThread_t::run(void)
{
char line[256];
char buf[8192];
int i,idx=0;
printf("Trace Log Disk Start\n");
if ( logFile == NULL )
{
return;
}
if ( logBuf == NULL )
{
size_t size;
size = logBufMax * sizeof(traceRecord_t);
logBufHead = logBufTail = 0;
logBuf = (traceRecord_t *)malloc(size);
}
idx = 0;
while ( !isInterruptionRequested() )
{
while (logBufHead != logBufTail)
{
logBuf[logBufTail].convToText(line);
i=0;
while ( line[i] != 0 )
{
buf[idx] = line[i]; i++; idx++;
}
buf[idx] = '\n'; idx++;
logBufTail = (logBufTail + 1) % logBufMax;
if ( idx >= 4096 )
{
fwrite( buf, idx, 1, logFile ); idx = 0;
}
}
SDL_Delay(10);
}
if ( idx > 0 )
{
fwrite( buf, idx, 1, logFile ); idx = 0;
}
if (logFile)
{
fclose(logFile);
logFile = NULL;
}
printf("Trace Log Disk Exit\n");
emit finished();
}
//----------------------------------------------------

View File

@ -131,6 +131,23 @@ private slots:
void ctxMenuAddSym(void); void ctxMenuAddSym(void);
}; };
class TraceLogDiskThread_t : public QThread
{
Q_OBJECT
protected:
void run( void ) override;
public:
TraceLogDiskThread_t( QObject *parent = 0 );
~TraceLogDiskThread_t(void);
private:
signals:
void finished(void);
};
class TraceLoggerDialog_t : public QDialog class TraceLoggerDialog_t : public QDialog
{ {
Q_OBJECT Q_OBJECT
@ -139,6 +156,8 @@ public:
TraceLoggerDialog_t(QWidget *parent = 0); TraceLoggerDialog_t(QWidget *parent = 0);
~TraceLoggerDialog_t(void); ~TraceLoggerDialog_t(void);
TraceLogDiskThread_t *diskThread;
void showBufferWarning(void); void showBufferWarning(void);
protected: protected:
QTimer *updateTimer; QTimer *updateTimer;