Fixed a bug in AbstractTool class that could cause a severe slow-down on process creation, especially with a large number of threads: The same mutex was used in the constructor and the startProcess() function, which is unnecessary anyway. But even worse, there was a sleep() call in the startProcess() function that could *block* the mutex for a very long time! So if the "main" thread tried to create a new object while one of the "worker" threads was sleeping inside startProcess(), this blocked the whole "main" thread. D'oh!

This commit is contained in:
LoRd_MuldeR 2014-12-05 22:39:31 +01:00
parent 8211b417d6
commit 67429fbada
5 changed files with 32 additions and 36 deletions

View File

@ -30,4 +30,7 @@ Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
EndGlobal

View File

@ -27,6 +27,8 @@ a:visited { color: #0000EE; }
<li>Updated Vorbis decoder to OggDec v1.10.1 (2014-06-25), using libVorbis v1.3.4
<li>Updated GnuPG to v1.4.18 (2014-06-30), compiled with GCC 4.9.1
<li>Fixed potential crash in Cue Sheet importer (occurred when *all* input files were missing)
<li>Fixed a severe performance bottleneck, especially with a large number of parallel instances
<li>The limit for the maximum number of parallel instances has been increased to 32
<li>Experimental support for Windows 10 Technical Preview
</ul><br>

View File

@ -34,8 +34,8 @@
#define VER_LAMEXP_MINOR_HI 1
#define VER_LAMEXP_MINOR_LO 1
#define VER_LAMEXP_TYPE Beta
#define VER_LAMEXP_PATCH 4
#define VER_LAMEXP_BUILD 1615
#define VER_LAMEXP_PATCH 5
#define VER_LAMEXP_BUILD 1616
#define VER_LAMEXP_CONFG 1558
///////////////////////////////////////////////////////////////////////////////

View File

@ -39,34 +39,33 @@
#include <QDir>
/*
* Static vars
* Job Object
*/
quint64 AbstractTool::s_lastLaunchTime = 0ui64;
QMutex AbstractTool::s_mutex_startProcess;
JobObject *AbstractTool::s_jobObject = NULL;
unsigned int AbstractTool::s_jobObjRefCount = 0U;
QScopedPointer<JobObject> AbstractTool::s_jobObject;
QMutex AbstractTool::s_jobObjMtx;
/*
* Process Timer
*/
quint64 AbstractTool::s_startProcessTimer = 0ui64;
QMutex AbstractTool::s_startProcessMutex;
/*
* Const
*/
static const unsigned int START_DELAY = 333; //in milliseconds
static const quint64 START_DELAY_NANO = START_DELAY * 1000 * 10; //in 100-nanosecond intervals
static const unsigned int START_DELAY = 50U; //in milliseconds
static const quint64 START_DELAY_NANO = quint64(START_DELAY) * 10000ui64; //in 100-nanosecond intervals
/*
* Constructor
*/
AbstractTool::AbstractTool(void)
{
QMutexLocker lock(&s_mutex_startProcess);
QMutexLocker lock(&s_jobObjMtx);
if(s_jobObjRefCount < 1U)
if(s_jobObject.isNull())
{
s_jobObject = new JobObject();
s_jobObjRefCount = 1U;
}
else
{
s_jobObjRefCount++;
s_jobObject.reset(new JobObject());
}
m_firstLaunch = true;
@ -77,16 +76,6 @@ AbstractTool::AbstractTool(void)
*/
AbstractTool::~AbstractTool(void)
{
QMutexLocker lock(&s_mutex_startProcess);
if(s_jobObjRefCount >= 1U)
{
s_jobObjRefCount--;
if(s_jobObjRefCount < 1U)
{
MUTILS_DELETE(s_jobObject);
}
}
}
/*
@ -94,11 +83,13 @@ AbstractTool::~AbstractTool(void)
*/
bool AbstractTool::startProcess(QProcess &process, const QString &program, const QStringList &args)
{
QMutexLocker lock(&s_mutex_startProcess);
QMutexLocker lock(&s_startProcessMutex);
if(MUtils::OS::current_file_time() <= s_lastLaunchTime)
while(MUtils::OS::current_file_time() <= s_startProcessTimer)
{
lock.unlock();
MUtils::OS::sleep_ms(START_DELAY);
lock.relock();
}
emit messageLogged(commandline2string(program, args) + "\n");
@ -117,7 +108,6 @@ bool AbstractTool::startProcess(QProcess &process, const QString &program, const
}
MUtils::OS::change_process_priority(&process, -1);
lock.unlock();
if(m_firstLaunch)
{
@ -125,7 +115,7 @@ bool AbstractTool::startProcess(QProcess &process, const QString &program, const
m_firstLaunch = false;
}
s_lastLaunchTime = MUtils::OS::current_file_time() + START_DELAY_NANO;
s_startProcessTimer = MUtils::OS::current_file_time() + START_DELAY_NANO;
return true;
}
@ -136,7 +126,7 @@ bool AbstractTool::startProcess(QProcess &process, const QString &program, const
process.kill();
process.waitForFinished(-1);
s_lastLaunchTime = MUtils::OS::current_file_time() + START_DELAY_NANO;
s_startProcessTimer = MUtils::OS::current_file_time() + START_DELAY_NANO;
return false;
}

View File

@ -47,10 +47,11 @@ protected:
static const int m_processTimeoutInterval = 600000;
private:
static quint64 s_lastLaunchTime;
static QMutex s_mutex_startProcess;
static unsigned int s_jobObjRefCount;
static JobObject *s_jobObject;
static quint64 s_startProcessTimer;
static QMutex s_startProcessMutex;
static QScopedPointer<JobObject> s_jobObject;
static QMutex s_jobObjMtx;
bool m_firstLaunch;
};