aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/corelib/buildgraph/processcommandexecutor.cpp
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2016-12-20 10:06:49 +0100
committerJoerg Bornemann <joerg.bornemann@qt.io>2017-01-25 11:30:02 +0000
commit557775b1ad3316ec158b9d930bf733b4fa502456 (patch)
tree1911bcdcf65c7ed1d106f101ef15e7083c56af7e /src/lib/corelib/buildgraph/processcommandexecutor.cpp
parentab89e84d71b277744df98a7037263e7bd44efbeb (diff)
Use a dedicated launcher process to run all ProcessCommands
On Linux (and very likely other Unices as well), QProcess::start() incurs a certain overhead, because forking off the child process duplicates some of the parent process' resources. This overhead appears to be proportional to the amount of memory allocated by the parent process, presumably due to page table entries getting copied. This has consequences for qbs, particularly when being used from an IDE such as Qt Creator, which has a higher memory footprint than the command line tool. When using a high job count, as is typical on machines with lots of CPU cores or in a distributed compilation environment, the following problems were observed: - High CPU load in the starting process (Qt Creator). Profiling showed that most of the time was spent in fork() and related functions. - As a result, the number of parallel jobs stalled at a value well below the requested one, slowing down the build. - In some cases, QProcess::start() failed altogether, emitting a message such as "fork() failed: Could not allocate memory". We solve these issues by outsourcing the starting of ProcessCommands to a dedicated launcher tool with modest memory requirements. For each qbs process, we have one instance of this tool running while a build job is going on. Communication with qbs happens via QLocalSocket. The protocol is encapsulated in a QProcess replacement, so almost no changes to existing code were necessary. No performance regressions were observed when using lower job counts. This patch will also enable us to properly support the incredibuild tool in IDEs such as Qt Creator, which you do not want to start via ibconsole. [ChangeLog] Improved scalability of parallel builds on Linux by starting Process commands via a dedicated launcher process. Change-Id: I8966c00a2d67a94c3a380f0e089d61eda122209e Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io> Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Diffstat (limited to 'src/lib/corelib/buildgraph/processcommandexecutor.cpp')
-rw-r--r--src/lib/corelib/buildgraph/processcommandexecutor.cpp8
1 files changed, 3 insertions, 5 deletions
diff --git a/src/lib/corelib/buildgraph/processcommandexecutor.cpp b/src/lib/corelib/buildgraph/processcommandexecutor.cpp
index 9eae591eb..befa66563 100644
--- a/src/lib/corelib/buildgraph/processcommandexecutor.cpp
+++ b/src/lib/corelib/buildgraph/processcommandexecutor.cpp
@@ -71,9 +71,9 @@ namespace Internal {
ProcessCommandExecutor::ProcessCommandExecutor(const Logger &logger, QObject *parent)
: AbstractCommandExecutor(logger, parent)
{
- connect(&m_process, static_cast<void (QProcess::*)(QProcess::ProcessError)>(&QProcess::error),
+ connect(&m_process, static_cast<void (QbsProcess::*)(QProcess::ProcessError)>(&QbsProcess::error),
this, &ProcessCommandExecutor::onProcessError);
- connect(&m_process, static_cast<void (QProcess::*)(int)>(&QProcess::finished),
+ connect(&m_process, static_cast<void (QbsProcess::*)(int)>(&QbsProcess::finished),
this, &ProcessCommandExecutor::onProcessFinished);
}
@@ -169,9 +169,7 @@ void ProcessCommandExecutor::cancel()
// We don't want this command to be reported as failing, since we explicitly terminated it.
disconnect(this, &ProcessCommandExecutor::reportProcessResult, 0, 0);
- m_process.terminate();
- if (!m_process.waitForFinished(1000))
- m_process.kill();
+ m_process.cancel();
}
QString ProcessCommandExecutor::filterProcessOutput(const QByteArray &_output,