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:
parent
8211b417d6
commit
67429fbada
@ -30,4 +30,7 @@ Global
|
|||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
GlobalSection(Performance) = preSolution
|
||||||
|
HasPerformanceSessions = true
|
||||||
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@ -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 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>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 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
|
<li>Experimental support for Windows 10 Technical Preview
|
||||||
</ul><br>
|
</ul><br>
|
||||||
|
|
||||||
|
@ -34,8 +34,8 @@
|
|||||||
#define VER_LAMEXP_MINOR_HI 1
|
#define VER_LAMEXP_MINOR_HI 1
|
||||||
#define VER_LAMEXP_MINOR_LO 1
|
#define VER_LAMEXP_MINOR_LO 1
|
||||||
#define VER_LAMEXP_TYPE Beta
|
#define VER_LAMEXP_TYPE Beta
|
||||||
#define VER_LAMEXP_PATCH 4
|
#define VER_LAMEXP_PATCH 5
|
||||||
#define VER_LAMEXP_BUILD 1615
|
#define VER_LAMEXP_BUILD 1616
|
||||||
#define VER_LAMEXP_CONFG 1558
|
#define VER_LAMEXP_CONFG 1558
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -39,34 +39,33 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Static vars
|
* Job Object
|
||||||
*/
|
*/
|
||||||
quint64 AbstractTool::s_lastLaunchTime = 0ui64;
|
QScopedPointer<JobObject> AbstractTool::s_jobObject;
|
||||||
QMutex AbstractTool::s_mutex_startProcess;
|
QMutex AbstractTool::s_jobObjMtx;
|
||||||
JobObject *AbstractTool::s_jobObject = NULL;
|
|
||||||
unsigned int AbstractTool::s_jobObjRefCount = 0U;
|
/*
|
||||||
|
* Process Timer
|
||||||
|
*/
|
||||||
|
quint64 AbstractTool::s_startProcessTimer = 0ui64;
|
||||||
|
QMutex AbstractTool::s_startProcessMutex;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Const
|
* Const
|
||||||
*/
|
*/
|
||||||
static const unsigned int START_DELAY = 333; //in milliseconds
|
static const unsigned int START_DELAY = 50U; //in milliseconds
|
||||||
static const quint64 START_DELAY_NANO = START_DELAY * 1000 * 10; //in 100-nanosecond intervals
|
static const quint64 START_DELAY_NANO = quint64(START_DELAY) * 10000ui64; //in 100-nanosecond intervals
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
AbstractTool::AbstractTool(void)
|
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_jobObject.reset(new JobObject());
|
||||||
s_jobObjRefCount = 1U;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s_jobObjRefCount++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_firstLaunch = true;
|
m_firstLaunch = true;
|
||||||
@ -77,16 +76,6 @@ AbstractTool::AbstractTool(void)
|
|||||||
*/
|
*/
|
||||||
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)
|
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);
|
MUtils::OS::sleep_ms(START_DELAY);
|
||||||
|
lock.relock();
|
||||||
}
|
}
|
||||||
|
|
||||||
emit messageLogged(commandline2string(program, args) + "\n");
|
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);
|
MUtils::OS::change_process_priority(&process, -1);
|
||||||
lock.unlock();
|
|
||||||
|
|
||||||
if(m_firstLaunch)
|
if(m_firstLaunch)
|
||||||
{
|
{
|
||||||
@ -125,7 +115,7 @@ bool AbstractTool::startProcess(QProcess &process, const QString &program, const
|
|||||||
m_firstLaunch = false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +126,7 @@ bool AbstractTool::startProcess(QProcess &process, const QString &program, const
|
|||||||
process.kill();
|
process.kill();
|
||||||
process.waitForFinished(-1);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,10 +47,11 @@ protected:
|
|||||||
static const int m_processTimeoutInterval = 600000;
|
static const int m_processTimeoutInterval = 600000;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static quint64 s_lastLaunchTime;
|
static quint64 s_startProcessTimer;
|
||||||
static QMutex s_mutex_startProcess;
|
static QMutex s_startProcessMutex;
|
||||||
static unsigned int s_jobObjRefCount;
|
|
||||||
static JobObject *s_jobObject;
|
static QScopedPointer<JobObject> s_jobObject;
|
||||||
|
static QMutex s_jobObjMtx;
|
||||||
|
|
||||||
bool m_firstLaunch;
|
bool m_firstLaunch;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user