Commit fa27cd79 authored by Oswald Buddenhagen's avatar Oswald Buddenhagen
Browse files

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: default avatarDaniel Teske <daniel.teske@digia.com>
parent 12652c20
......@@ -1482,7 +1482,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
......@@ -1840,35 +1840,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)) {
......
......@@ -43,9 +43,13 @@
#include <qstack.h>
#include <qstring.h>
#include <qstringlist.h>
#include <qshareddata.h>
#ifndef QT_BOOTSTRAPPED
# include <qprocess.h>
#endif
#ifdef PROEVALUATOR_THREAD_SAFE
# include <qmutex.h>
#endif
QT_BEGIN_NAMESPACE
......@@ -71,6 +75,20 @@ public:
virtual void doneWithEval(ProFile *parent) = 0;
};
typedef QPair<QString, QString> QMakeFeatureKey; // key, parent
typedef QHash<QMakeFeatureKey, QString> 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<ProValueMap>
......@@ -271,7 +289,7 @@ public:
QStringList m_qmakepath;
QStringList m_qmakefeatures;
QStringList m_mkspecPaths;
QStringList m_featureRoots;
QExplicitlySharedDataPointer<QMakeFeatureRoots> m_featureRoots;
ProString m_dirSep;
ProFunctionDefs m_functionDefs;
ProStringList m_returnValue;
......
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