From: Oswald Buddenhagen Date: Mon, 3 Jun 2013 17:08:10 +0000 (+0200) Subject: cache results of feature search X-Git-Tag: accepted/tizen/20131212.181521~83^2~21 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4bc46c211bb4c1462e86980a1451b7ebc99bb583;p=platform%2Fupstream%2Fqttools.git cache results of feature search looking up the same files in the same locations over and over again is a rather significant waste. in particular, looking up the CONFIG flags that don't correspond with features has a measurable impact on qt creator's project loading time. Task-number: QTCREATORBUG-9154 Change-Id: Ibae3d8b7797e706a6416a7d45c77734ab1281b51 Reviewed-by: Daniel Teske (cherry picked from qtcreator/fa27cd79e05aed4ebd16d5648480cc7d48fefd43) --- diff --git a/src/linguist/shared/qmakeevaluator.cpp b/src/linguist/shared/qmakeevaluator.cpp index e080c15..281385a 100644 --- a/src/linguist/shared/qmakeevaluator.cpp +++ b/src/linguist/shared/qmakeevaluator.cpp @@ -1499,7 +1499,7 @@ void QMakeEvaluator::updateFeaturePaths() foreach (const QString &root, feature_roots) if (IoUtils::exists(root)) ret << root; - m_featureRoots = ret; + m_featureRoots = new QMakeFeatureRoots(ret); } ProString QMakeEvaluator::propertyValue(const ProKey &name) const @@ -1857,35 +1857,55 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFeatureFile( if (!fn.endsWith(QLatin1String(".prf"))) fn += QLatin1String(".prf"); - if (m_featureRoots.isEmpty()) + if (!m_featureRoots) updateFeaturePaths(); - int start_root = 0; +#ifdef PROEVALUATOR_THREAD_SAFE + m_featureRoots->mutex.lock(); +#endif QString currFn = currentFileName(); - if (IoUtils::fileName(currFn) == IoUtils::fileName(fn)) { - QStringRef currPath = IoUtils::pathName(currFn); - for (int root = 0; root < m_featureRoots.size(); ++root) - if (currPath == m_featureRoots.at(root)) { - start_root = root + 1; - break; + if (IoUtils::fileName(currFn) != IoUtils::fileName(fn)) + currFn.clear(); + // Null values cannot regularly exist in the hash, so they indicate that the value still + // needs to be determined. Failed lookups are represented via non-null empty strings. + QString *fnp = &m_featureRoots->cache[qMakePair(fn, currFn)]; + if (fnp->isNull()) { + int start_root = 0; + const QStringList &paths = m_featureRoots->paths; + if (!currFn.isEmpty()) { + QStringRef currPath = IoUtils::pathName(currFn); + for (int root = 0; root < paths.size(); ++root) + if (currPath == paths.at(root)) { + start_root = root + 1; + break; + } + } + for (int root = start_root; root < paths.size(); ++root) { + QString fname = paths.at(root) + fn; + if (IoUtils::exists(fname)) { + fn = fname; + goto cool; } - } - for (int root = start_root; root < m_featureRoots.size(); ++root) { - QString fname = m_featureRoots.at(root) + fn; - if (IoUtils::exists(fname)) { - fn = fname; - goto cool; } - } #ifdef QMAKE_BUILTIN_PRFS - fn.prepend(QLatin1String(":/qmake/features/")); - if (QFileInfo(fn).exists()) - goto cool; + fn.prepend(QLatin1String(":/qmake/features/")); + if (QFileInfo(fn).exists()) + goto cool; #endif - if (!silent) - evalError(fL1S("Cannot find feature %1").arg(fileName)); - return ReturnFalse; + fn = QLatin1String(""); // Indicate failed lookup. See comment above. - cool: + cool: + *fnp = fn; + } else { + fn = *fnp; + } +#ifdef PROEVALUATOR_THREAD_SAFE + m_featureRoots->mutex.unlock(); +#endif + if (fn.isEmpty()) { + if (!silent) + evalError(fL1S("Cannot find feature %1").arg(fileName)); + return ReturnFalse; + } ProStringList &already = valuesRef(ProKey("QMAKE_INTERNAL_INCLUDED_FEATURES")); ProString afn(fn); if (already.contains(afn)) { diff --git a/src/linguist/shared/qmakeevaluator.h b/src/linguist/shared/qmakeevaluator.h index f4e65e3..548c2d6 100644 --- a/src/linguist/shared/qmakeevaluator.h +++ b/src/linguist/shared/qmakeevaluator.h @@ -55,9 +55,13 @@ #include #include #include +#include #ifndef QT_BOOTSTRAPPED # include #endif +#ifdef PROEVALUATOR_THREAD_SAFE +# include +#endif QT_BEGIN_NAMESPACE @@ -83,6 +87,20 @@ public: virtual void doneWithEval(ProFile *parent) = 0; }; +typedef QPair QMakeFeatureKey; // key, parent +typedef QHash QMakeFeatureHash; + +class QMAKE_EXPORT QMakeFeatureRoots : public QSharedData +{ +public: + QMakeFeatureRoots(const QStringList &_paths) : paths(_paths) {} + const QStringList paths; + mutable QMakeFeatureHash cache; +#ifdef PROEVALUATOR_THREAD_SAFE + mutable QMutex mutex; +#endif +}; + // We use a QLinkedList based stack instead of a QVector based one (QStack), so that // the addresses of value maps stay constant. The qmake generators rely on that. class QMAKE_EXPORT ProValueMapStack : public QLinkedList @@ -283,7 +301,7 @@ public: QStringList m_qmakepath; QStringList m_qmakefeatures; QStringList m_mkspecPaths; - QStringList m_featureRoots; + QExplicitlySharedDataPointer m_featureRoots; ProString m_dirSep; ProFunctionDefs m_functionDefs; ProStringList m_returnValue;