From e38361b5a8bbcd963954aaa895e7f91a967bf324 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Tue, 10 Sep 2019 23:39:29 +0300 Subject: Lower priority on build This should prevent slowdown of the IDE (and the rest of the system) while building with all the CPU cores. Fixes: QTCREATORBUG-5155 Change-Id: Icaadc53958f2d8e918035463e3c9344c91235615 Reviewed-by: hjk --- src/libs/utils/process_ctrlc_stub.cpp | 16 +++++++++---- src/libs/utils/qtcprocess.cpp | 26 +++++++++++++++++++++- src/libs/utils/qtcprocess.h | 4 ++++ src/plugins/cmakeprojectmanager/cmakebuildstep.cpp | 2 ++ .../projectexplorer/abstractprocessstep.cpp | 8 +++++++ src/plugins/projectexplorer/abstractprocessstep.h | 1 + src/plugins/projectexplorer/makestep.cpp | 1 + src/plugins/qmakeprojectmanager/qmakestep.cpp | 1 + 8 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/libs/utils/process_ctrlc_stub.cpp b/src/libs/utils/process_ctrlc_stub.cpp index 396ed3c153..e5469e208d 100644 --- a/src/libs/utils/process_ctrlc_stub.cpp +++ b/src/libs/utils/process_ctrlc_stub.cpp @@ -45,6 +45,7 @@ const wchar_t szTitle[] = L"qtcctrlcstub"; const wchar_t szWindowClass[] = L"wcqtcctrlcstub"; +const wchar_t szNice[] = L"-nice "; UINT uiShutDownWindowMessage; UINT uiInterruptMessage; HWND hwndMain = nullptr; @@ -53,7 +54,7 @@ LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); BOOL WINAPI shutdownHandler(DWORD dwCtrlType); BOOL WINAPI interruptHandler(DWORD dwCtrlType); bool isSpaceOrTab(const wchar_t c); -bool startProcess(wchar_t pCommandLine[]); +bool startProcess(wchar_t pCommandLine[], bool lowerPriority); int main(int argc, char **) { @@ -93,7 +94,14 @@ int main(int argc, char **) ++pos; } - bool bSuccess = startProcess(strCommandLine + pos); + const size_t niceLen = wcslen(szNice); + bool lowerPriority = !wcsncmp(strCommandLine + pos, szNice, niceLen); + if (lowerPriority) { + pos += niceLen - 1; // reach the space, then the following line skips all spaces. + while (isSpaceOrTab(strCommandLine[++pos])) + ; + } + bool bSuccess = startProcess(strCommandLine + pos, lowerPriority); free(strCommandLine); if (!bSuccess) @@ -166,7 +174,7 @@ DWORD WINAPI processWatcherThread(LPVOID lpParameter) return 0; } -bool startProcess(wchar_t *pCommandLine) +bool startProcess(wchar_t *pCommandLine, bool lowerPriority) { SECURITY_ATTRIBUTES sa = {0}; sa.nLength = sizeof(sa); @@ -176,7 +184,7 @@ bool startProcess(wchar_t *pCommandLine) si.cb = sizeof(si); PROCESS_INFORMATION pi; - DWORD dwCreationFlags = 0; + DWORD dwCreationFlags = lowerPriority ? BELOW_NORMAL_PRIORITY_CLASS : 0; BOOL bSuccess = CreateProcess(NULL, pCommandLine, &sa, &sa, TRUE, dwCreationFlags, NULL, NULL, &si, &pi); if (!bSuccess) { fwprintf(stderr, L"qtcreator_ctrlc_stub: Command line failed: %s\n", pCommandLine); diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp index 557f77fd34..6d608a441b 100644 --- a/src/libs/utils/qtcprocess.cpp +++ b/src/libs/utils/qtcprocess.cpp @@ -37,6 +37,9 @@ #ifdef Q_OS_WIN #include +#else +#include +#include #endif @@ -712,9 +715,17 @@ void QtcProcess::start() if (osType == OsTypeWindows) { QString args; if (m_useCtrlCStub) { - args = QtcProcess::quoteArg(QDir::toNativeSeparators(command)); + if (m_lowPriority) + addArg(&args, "-nice"); + addArg(&args, QDir::toNativeSeparators(command)); command = QCoreApplication::applicationDirPath() + QLatin1String("/qtcreator_ctrlc_stub.exe"); + } else if (m_lowPriority) { +#ifdef Q_OS_WIN + setCreateProcessArgumentsModifier([](CreateProcessArguments *args) { + args->flags |= BELOW_NORMAL_PRIORITY_CLASS; + }); +#endif } QtcProcess::addArgs(&args, arguments.toWindowsArgs()); #ifdef Q_OS_WIN @@ -1208,6 +1219,19 @@ QString QtcProcess::expandMacros(const QString &str, AbstractMacroExpander *mx, return ret; } +void QtcProcess::setupChildProcess() +{ +#if defined Q_OS_UNIX + // nice value range is -20 to +19 where -20 is highest, 0 default and +19 is lowest + if (m_lowPriority) { + errno = 0; + if (::nice(5) == -1 && errno != 0) + qWarning("Failed to set nice value. Error: %d", errno); + } +#endif + QProcess::setupChildProcess(); +} + bool QtcProcess::ArgIterator::next() { // We delay the setting of m_prev so we can still delete the last argument diff --git a/src/libs/utils/qtcprocess.h b/src/libs/utils/qtcprocess.h index 5eeacf666e..ca3f9a5a86 100644 --- a/src/libs/utils/qtcprocess.h +++ b/src/libs/utils/qtcprocess.h @@ -45,6 +45,7 @@ public: void start(); void terminate(); void interrupt(); + void setLowPriority() { m_lowPriority = true; } class QTCREATOR_UTILS_EXPORT Arguments { @@ -141,10 +142,13 @@ public: }; private: + void setupChildProcess() override; + CommandLine m_commandLine; Environment m_environment; bool m_haveEnv = false; bool m_useCtrlCStub = false; + bool m_lowPriority = false; }; } // namespace Utils diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp index 5076d816ef..68b514d6f1 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp @@ -87,6 +87,8 @@ CMakeBuildStep::CMakeBuildStep(BuildStepList *bsl) : if (m_buildTarget.isEmpty()) setBuildTarget(defaultBuildTarget()); + setLowPriority(); + connect(target(), &Target::kitChanged, this, &CMakeBuildStep::cmakeCommandChanged); connect(project(), &Project::parsingFinished, this, &CMakeBuildStep::handleBuildTargetChanges); diff --git a/src/plugins/projectexplorer/abstractprocessstep.cpp b/src/plugins/projectexplorer/abstractprocessstep.cpp index ba1c590fe4..de80337d55 100644 --- a/src/plugins/projectexplorer/abstractprocessstep.cpp +++ b/src/plugins/projectexplorer/abstractprocessstep.cpp @@ -109,6 +109,7 @@ public: QByteArray deferredText; bool m_ignoreReturnValue = false; bool m_skipFlush = false; + bool m_lowPriority = false; void readData(void (AbstractProcessStep::*func)(const QString &), bool isUtf8 = false); void processLine(const QByteArray &data, @@ -227,6 +228,8 @@ void AbstractProcessStep::doRun() d->m_process->setWorkingDirectory(wd.absolutePath()); d->m_process->setEnvironment(d->m_param.environment()); d->m_process->setCommand(effectiveCommand); + if (d->m_lowPriority) + d->m_process->setLowPriority(); connect(d->m_process.get(), &QProcess::readyReadStandardOutput, this, &AbstractProcessStep::processReadyReadStdOutput); @@ -246,6 +249,11 @@ void AbstractProcessStep::doRun() processStarted(); } +void AbstractProcessStep::setLowPriority() +{ + d->m_lowPriority = true; +} + void AbstractProcessStep::doCancel() { Core::Reaper::reap(d->m_process.release()); diff --git a/src/plugins/projectexplorer/abstractprocessstep.h b/src/plugins/projectexplorer/abstractprocessstep.h index b21a6bdb25..3cc7aa8bf5 100644 --- a/src/plugins/projectexplorer/abstractprocessstep.h +++ b/src/plugins/projectexplorer/abstractprocessstep.h @@ -57,6 +57,7 @@ protected: ~AbstractProcessStep() override; bool init() override; void doRun() override; + void setLowPriority(); virtual void finish(bool success); virtual void processStarted(); diff --git a/src/plugins/projectexplorer/makestep.cpp b/src/plugins/projectexplorer/makestep.cpp index dece53ad6f..8961cd718d 100644 --- a/src/plugins/projectexplorer/makestep.cpp +++ b/src/plugins/projectexplorer/makestep.cpp @@ -65,6 +65,7 @@ MakeStep::MakeStep(BuildStepList *parent, Core::Id id) m_userJobCount(defaultJobCount()) { setDefaultDisplayName(defaultDisplayName()); + setLowPriority(); } void MakeStep::setBuildTarget(const QString &buildTarget) diff --git a/src/plugins/qmakeprojectmanager/qmakestep.cpp b/src/plugins/qmakeprojectmanager/qmakestep.cpp index 511b44ac96..f8ca59f594 100644 --- a/src/plugins/qmakeprojectmanager/qmakestep.cpp +++ b/src/plugins/qmakeprojectmanager/qmakestep.cpp @@ -76,6 +76,7 @@ QMakeStep::QMakeStep(BuildStepList *bsl) : AbstractProcessStep(bsl, Constants::Q { //: QMakeStep default display name setDefaultDisplayName(tr("qmake")); + setLowPriority(); } QmakeBuildConfiguration *QMakeStep::qmakeBuildConfiguration() const -- cgit v1.2.1