Commit f2a6941e authored by Milian Wolff's avatar Milian Wolff

Cache ProblemPointers per translation unit

For visibility purposes, all 'inclue file not found' errors are
associated with all files in a TU, since these usually completely
break the interpretation of a file. But in some situations, this
triggers a severe performance degradation:

When the TU has a deep include stack depth and a file is not found
somewhere at the bottom of the stack, then it will have one child
diagnostic for every "included from ..." file higher up in the stack.
Now if we would repeatedly build and intern the KDevelop::Problem
representation for these diagnostics, for every file in the TU, we
sometimes ended up spending *minutes* to create all the problems
in ParseSession::problemsForFile!

To workaround this situation, cache the ProblemPointer in the
ParseSessionData for a given translation unit. This way, we will
only convert a given diagnostic and its child diagnostics once per TU
instead of once per file contained in a TU.

In my case this brings down the time spent in problemsForFile for a
single TU from ~7min (sic!) down to ~12s. While the latter is still
a lot, this is already much more bearable.

BUG: 386720

Reviewers: #kdevelop

Subscribers: kdevelop-devel

Differential Revision:
parent 3881efbd
......@@ -380,6 +380,7 @@ QByteArray ParseSessionData::writeDefinesFile(const QMap<QString, QString>& defi
void ParseSessionData::setUnit(CXTranslationUnit unit)
m_unit = unit;
if (m_unit) {
const ClangString unitFile(clang_getTranslationUnitSpelling(unit));
m_file = clang_getFile(m_unit, unitFile.c_str());
......@@ -449,6 +450,8 @@ QList<ProblemPointer> ParseSession::problemsForFile(CXFile file) const
// extra clang diagnostics
const uint numDiagnostics = clang_getNumDiagnostics(d->m_unit);
for (uint i = 0; i < numDiagnostics; ++i) {
auto diagnostic = clang_getDiagnostic(d->m_unit, i);
......@@ -461,7 +464,11 @@ QList<ProblemPointer> ParseSession::problemsForFile(CXFile file) const
ProblemPointer problem(ClangDiagnosticEvaluator::createProblem(diagnostic, d->m_unit));
auto& problem = d->m_diagnosticsCache[i];
if (!problem) {
problem = ClangDiagnosticEvaluator::createProblem(diagnostic, d->m_unit);
problems << problem;
......@@ -79,6 +79,8 @@ private:
/// TODO: share this file for all TUs that use the same defines (probably most in a project)
/// best would be a PCH, if possible
QTemporaryFile m_definesFile;
// cached ProblemPointer representation for diagnostics
QVector<KDevelop::ProblemPointer> m_diagnosticsCache;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment