diff options
author | Antonio Di Monaco <tony@becrux.com> | 2018-03-28 12:37:19 +0200 |
---|---|---|
committer | Antonio Di Monaco <tony@becrux.com> | 2018-04-13 16:04:08 +0000 |
commit | 5784fce2449485b627327f88f96301298987941f (patch) | |
tree | ef2096a8a85b5ef7159197de6d89afe6cbb3259e /src/plugins/projectexplorer/abstractprocessstep.cpp | |
parent | a8eeb10630aaff53b28dfc2f2927fd91077f33bb (diff) |
Fix UI freeze while building with multiple cores / distributed build
When parallelizing the build, and a verbose compiler error/warning
is printed (i.e. a template overload error), the IDE wastes a lot
of time parsing always the same file patterns, and that freezes
completely the UI. The only workaround is to kill the build process
using a terminal.
Implement a file cache, thus mitigating the freeze issue.
Change-Id: Ibcbdb6e6161af7cef424e90f7cfdc2fc34f6d7c1
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
Reviewed-by: Antonio Di Monaco <tony@becrux.com>
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
Diffstat (limited to 'src/plugins/projectexplorer/abstractprocessstep.cpp')
-rw-r--r-- | src/plugins/projectexplorer/abstractprocessstep.cpp | 65 |
1 files changed, 51 insertions, 14 deletions
diff --git a/src/plugins/projectexplorer/abstractprocessstep.cpp b/src/plugins/projectexplorer/abstractprocessstep.cpp index bfd7f0ef1d..2634cdd4b5 100644 --- a/src/plugins/projectexplorer/abstractprocessstep.cpp +++ b/src/plugins/projectexplorer/abstractprocessstep.cpp @@ -36,6 +36,13 @@ #include <QTimer> #include <QDir> +#include <algorithm> + +namespace { +const int CACHE_SOFT_LIMIT = 500; +const int CACHE_HARD_LIMIT = 1000; +} // namespace + using namespace ProjectExplorer; /*! @@ -153,6 +160,12 @@ void AbstractProcessStep::setIgnoreReturnValue(bool b) bool AbstractProcessStep::init(QList<const BuildStep *> &earlierSteps) { Q_UNUSED(earlierSteps); + + m_candidates.clear(); + const Utils::FileNameList fl = project()->files(Project::AllFiles); + for (const Utils::FileName &file : fl) + m_candidates[file.fileName()].push_back(file); + return !m_process; } @@ -365,42 +378,46 @@ void AbstractProcessStep::taskAdded(const Task &task, int linkedOutputLines, int Task editable(task); QString filePath = task.file.toString(); - if (!filePath.isEmpty() && !filePath.startsWith('<') && !QDir::isAbsolutePath(filePath)) { + + auto it = m_filesCache.find(filePath); + if (it != m_filesCache.end()) { + editable.file = it.value().first; + it.value().second = ++m_cacheCounter; + } else if (!filePath.isEmpty() && !filePath.startsWith('<') && !QDir::isAbsolutePath(filePath)) { // We have no save way to decide which file in which subfolder // is meant. Therefore we apply following heuristics: // 1. Check if file is unique in whole project // 2. Otherwise try again without any ../ // 3. give up. - QList<QFileInfo> possibleFiles; - QString fileName = Utils::FileName::fromString(filePath).fileName(); - foreach (const Utils::FileName &file, project()->files(Project::AllFiles)) { - QFileInfo candidate = file.toFileInfo(); - if (candidate.fileName() == fileName) - possibleFiles << candidate; - } + QString sourceFilePath = filePath; + Utils::FileNameList possibleFiles = m_candidates.value(Utils::FileName::fromString(filePath).fileName()); if (possibleFiles.count() == 1) { - editable.file = Utils::FileName(possibleFiles.first()); + editable.file = possibleFiles.first(); } else { // More then one filename, so do a better compare // Chop of any "../" while (filePath.startsWith("../")) filePath.remove(0, 3); + int count = 0; - QString possibleFilePath; - foreach (const QFileInfo &fi, possibleFiles) { - if (fi.filePath().endsWith(filePath)) { - possibleFilePath = fi.filePath(); + Utils::FileName possibleFilePath; + foreach (const Utils::FileName &fn, possibleFiles) { + if (fn.endsWith(filePath)) { + possibleFilePath = fn; ++count; } } if (count == 1) - editable.file = Utils::FileName::fromString(possibleFilePath); + editable.file = possibleFilePath; else qWarning() << "Could not find absolute location of file " << filePath; } + + insertInCache(sourceFilePath, editable.file); } + emit addTask(editable, linkedOutputLines, skipLines); } @@ -425,5 +442,25 @@ void AbstractProcessStep::slotProcessFinished(int, QProcess::ExitStatus) for (const QString &l : stdOutLine.split('\n')) stdError(l); + purgeCache(true); cleanUp(process); } + +void AbstractProcessStep::purgeCache(bool useSoftLimit) +{ + const int limit = useSoftLimit ? CACHE_SOFT_LIMIT : CACHE_HARD_LIMIT; + if (m_filesCache.size() <= limit) + return; + + const quint64 minCounter = m_cacheCounter - static_cast<quint64>(limit); + std::remove_if(m_filesCache.begin(), m_filesCache.end(), + [minCounter](const QPair<Utils::FileName, quint64> &entry) { + return entry.second <= minCounter; + }); +} + +void AbstractProcessStep::insertInCache(const QString &relativePath, const Utils::FileName &absPath) +{ + purgeCache(false); + m_filesCache.insert(relativePath, qMakePair(absPath, ++m_cacheCounter)); +} |