forked from qt-creator/qt-creator
cache parsed pri & prf files
no point in re-parsing them over and over during the scan of a bigger project ... shaves off another 20% of the loading time of Qt 4.6.
This commit is contained in:
@@ -42,35 +42,27 @@ ProFileReader::ProFileReader(ProFileOption *option) : ProFileEvaluator(option)
|
||||
ProFileReader::~ProFileReader()
|
||||
{
|
||||
foreach (ProFile *pf, m_proFiles)
|
||||
delete pf;
|
||||
pf->deref();
|
||||
}
|
||||
|
||||
bool ProFileReader::readProFile(const QString &fileName)
|
||||
{
|
||||
//disable caching -> list of include files is not updated otherwise
|
||||
ProFile *pro = new ProFile(fileName);
|
||||
if (!queryProFile(pro)) {
|
||||
delete pro;
|
||||
return false;
|
||||
if (ProFile *pro = parsedProFile(fileName)) {
|
||||
aboutToEval(pro);
|
||||
bool ok = accept(pro);
|
||||
pro->deref();
|
||||
return ok;
|
||||
}
|
||||
m_includeFiles.insert(fileName, pro);
|
||||
m_proFiles.append(pro);
|
||||
return accept(pro);
|
||||
return false;
|
||||
}
|
||||
|
||||
ProFile *ProFileReader::parsedProFile(const QString &fileName)
|
||||
void ProFileReader::aboutToEval(ProFile *pro)
|
||||
{
|
||||
ProFile *pro = ProFileEvaluator::parsedProFile(fileName);
|
||||
if (pro) {
|
||||
m_includeFiles.insert(fileName, pro);
|
||||
if (!m_includeFiles.contains(pro->fileName())) {
|
||||
m_includeFiles.insert(pro->fileName(), pro);
|
||||
m_proFiles.append(pro);
|
||||
pro->ref();
|
||||
}
|
||||
return pro;
|
||||
}
|
||||
|
||||
void ProFileReader::releaseParsedProFile(ProFile *)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QList<ProFile*> ProFileReader::includeFiles() const
|
||||
@@ -117,3 +109,52 @@ ProFile *ProFileReader::proFileFor(const QString &name)
|
||||
{
|
||||
return m_includeFiles.value(name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
ProFileCacheManager *ProFileCacheManager::s_instance = 0;
|
||||
|
||||
ProFileCacheManager::ProFileCacheManager(QObject *parent) :
|
||||
QObject(parent),
|
||||
m_cache(0)
|
||||
{
|
||||
s_instance = this;
|
||||
m_timer.setSingleShot(true);
|
||||
m_timer.setInterval(5000);
|
||||
connect(&m_timer, SIGNAL(timeout()), SLOT(clear()));
|
||||
}
|
||||
|
||||
ProFileCacheManager::~ProFileCacheManager()
|
||||
{
|
||||
s_instance = 0;
|
||||
clear();
|
||||
}
|
||||
|
||||
ProFileCache *ProFileCacheManager::cache()
|
||||
{
|
||||
m_timer.start();
|
||||
if (!m_cache)
|
||||
m_cache = new ProFileCache;
|
||||
return m_cache;
|
||||
}
|
||||
|
||||
void ProFileCacheManager::clear()
|
||||
{
|
||||
// Just deleting the cache will be safe as long as the sequence of
|
||||
// obtaining a cache pointer and using it is atomic as far as the main
|
||||
// loop is concerned. Use a shared pointer once this is not true anymore.
|
||||
delete m_cache;
|
||||
m_cache = 0;
|
||||
}
|
||||
|
||||
void ProFileCacheManager::discardFiles(const QString &prefix)
|
||||
{
|
||||
if (m_cache)
|
||||
m_cache->discardFiles(prefix);
|
||||
}
|
||||
|
||||
void ProFileCacheManager::discardFile(const QString &fileName)
|
||||
{
|
||||
if (m_cache)
|
||||
m_cache->discardFile(fileName);
|
||||
}
|
||||
|
@@ -34,6 +34,7 @@
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
namespace Qt4ProjectManager {
|
||||
namespace Internal {
|
||||
@@ -56,8 +57,7 @@ signals:
|
||||
void errorFound(const QString &error);
|
||||
|
||||
private:
|
||||
virtual ProFile *parsedProFile(const QString &fileName);
|
||||
virtual void releaseParsedProFile(ProFile *proFile);
|
||||
virtual void aboutToEval(ProFile *proFile);
|
||||
virtual void logMessage(const QString &msg);
|
||||
virtual void fileMessage(const QString &msg);
|
||||
virtual void errorMessage(const QString &msg);
|
||||
@@ -67,6 +67,28 @@ private:
|
||||
QList<ProFile *> m_proFiles;
|
||||
};
|
||||
|
||||
class ProFileCacheManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static ProFileCacheManager *instance() { return s_instance; }
|
||||
ProFileCache *cache();
|
||||
void discardFiles(const QString &prefix);
|
||||
void discardFile(const QString &fileName);
|
||||
|
||||
private:
|
||||
ProFileCacheManager(QObject *parent);
|
||||
~ProFileCacheManager();
|
||||
Q_SLOT void clear();
|
||||
QTimer m_timer;
|
||||
ProFileCache *m_cache;
|
||||
|
||||
static ProFileCacheManager *s_instance;
|
||||
|
||||
friend class Qt4ProjectManagerPlugin;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Qt4ProjectManager
|
||||
|
||||
|
@@ -115,6 +115,7 @@ Qt4PriFileNode::Qt4PriFileNode(Qt4Project *project, Qt4ProFileNode* qt4ProFileNo
|
||||
|
||||
void Qt4PriFileNode::scheduleUpdate()
|
||||
{
|
||||
ProFileCacheManager::instance()->discardFile(m_projectFilePath);
|
||||
m_qt4ProFileNode->scheduleUpdate();
|
||||
}
|
||||
|
||||
|
@@ -867,6 +867,8 @@ ProFileReader *Qt4Project::createProFileReader(Qt4ProFileNode *qt4ProFileNode)
|
||||
if (version->isValid())
|
||||
m_proFileOption->properties = version->versionInfo();
|
||||
}
|
||||
|
||||
m_proFileOption->cache = ProFileCacheManager::instance()->cache();
|
||||
}
|
||||
++m_proFileOptionRefCnt;
|
||||
|
||||
@@ -883,6 +885,11 @@ void Qt4Project::destroyProFileReader(ProFileReader *reader)
|
||||
{
|
||||
delete reader;
|
||||
if (!--m_proFileOptionRefCnt) {
|
||||
QString dir = QFileInfo(m_fileInfo->fileName()).absolutePath();
|
||||
if (!dir.endsWith(QLatin1Char('/')))
|
||||
dir += QLatin1Char('/');
|
||||
m_proFileOption->cache->discardFiles(dir);
|
||||
|
||||
delete m_proFileOption;
|
||||
m_proFileOption = 0;
|
||||
}
|
||||
@@ -1040,8 +1047,10 @@ void Qt4Project::notifyChanged(const QString &name)
|
||||
if (files(Qt4Project::ExcludeGeneratedFiles).contains(name)) {
|
||||
QList<Qt4ProFileNode *> list;
|
||||
findProFile(name, rootProjectNode(), list);
|
||||
foreach(Qt4ProFileNode *node, list)
|
||||
foreach(Qt4ProFileNode *node, list) {
|
||||
ProFileCacheManager::instance()->discardFile(name);
|
||||
node->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -169,6 +169,8 @@ bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString *
|
||||
addAutoReleasedObject(MaemoManager::instance());
|
||||
#endif
|
||||
|
||||
new ProFileCacheManager(this);
|
||||
|
||||
// TODO reenable
|
||||
//m_embeddedPropertiesPage = new EmbeddedPropertiesPage;
|
||||
//addObject(m_embeddedPropertiesPage);
|
||||
|
@@ -1207,6 +1207,7 @@ void QtVersion::updateToolChainAndMkspec() const
|
||||
|
||||
ProFileOption option;
|
||||
option.properties = versionInfo();
|
||||
option.cache = ProFileCacheManager::instance()->cache();
|
||||
ProFileReader *reader = new ProFileReader(&option);
|
||||
reader->setCumulative(false);
|
||||
reader->setParsePreAndPostFiles(false);
|
||||
|
@@ -83,13 +83,61 @@ static void clearFunctions(ProFileEvaluator::FunctionDefs *defs)
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ProFileCache
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
ProFileCache::~ProFileCache()
|
||||
{
|
||||
foreach (ProFile *pro, parsed_files)
|
||||
pro->deref();
|
||||
}
|
||||
|
||||
void ProFileCache::discardFile(const QString &fileName)
|
||||
{
|
||||
QHash<QString, ProFile *>::Iterator it = parsed_files.find(fileName);
|
||||
if (it != parsed_files.end()) {
|
||||
it.value()->deref();
|
||||
parsed_files.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void ProFileCache::discardFiles(const QString &prefix)
|
||||
{
|
||||
QHash<QString, ProFile *>::Iterator
|
||||
it = parsed_files.begin(),
|
||||
end = parsed_files.end();
|
||||
while (it != end)
|
||||
if (it.key().startsWith(prefix)) {
|
||||
it.value()->deref();
|
||||
it = parsed_files.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void ProFileCache::addFile(ProFile *pro)
|
||||
{
|
||||
parsed_files[pro->fileName()] = pro;
|
||||
pro->ref();
|
||||
}
|
||||
|
||||
ProFile *ProFileCache::getFile(const QString &fileName)
|
||||
{
|
||||
ProFile *pro = parsed_files.value(fileName);
|
||||
if (pro)
|
||||
pro->ref();
|
||||
return pro;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ProFileOption
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ProFileOption
|
||||
ProFileOption::ProFileOption()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
@@ -112,6 +160,8 @@ ProFileOption::ProFileOption()
|
||||
#endif
|
||||
|
||||
field_sep = QLatin1String(" ");
|
||||
|
||||
cache = 0;
|
||||
}
|
||||
|
||||
ProFileOption::~ProFileOption()
|
||||
@@ -199,6 +249,8 @@ public:
|
||||
ProFile *currentProFile() const;
|
||||
|
||||
ProItem::ProItemReturn evaluateConditionalFunction(const QString &function, const QString &arguments);
|
||||
ProFile *parsedProFile(const QString &fileName, bool cache,
|
||||
const QString &contents = QString());
|
||||
bool evaluateFile(const QString &fileName);
|
||||
bool evaluateFeatureFile(const QString &fileName,
|
||||
QHash<QString, QStringList> *values = 0, FunctionDefs *defs = 0);
|
||||
@@ -2776,20 +2828,20 @@ QStringList ProFileEvaluator::Private::values(const QString &variableName, const
|
||||
return values(variableName, m_filevaluemap[pro], pro);
|
||||
}
|
||||
|
||||
// virtual
|
||||
ProFile *ProFileEvaluator::parsedProFile(const QString &fileName)
|
||||
ProFile *ProFileEvaluator::Private::parsedProFile(const QString &fileName, bool cache,
|
||||
const QString &contents)
|
||||
{
|
||||
ProFile *pro = new ProFile(fileName);
|
||||
if (d->read(pro))
|
||||
return pro;
|
||||
delete pro;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// virtual
|
||||
void ProFileEvaluator::releaseParsedProFile(ProFile *proFile)
|
||||
{
|
||||
delete proFile;
|
||||
ProFile *pro;
|
||||
if (!m_option->cache || !(pro = m_option->cache->getFile(fileName))) {
|
||||
pro = new ProFile(fileName);
|
||||
if (!(contents.isNull() ? read(pro) : read(pro, contents))) {
|
||||
delete pro;
|
||||
return 0;
|
||||
}
|
||||
if (m_option->cache && cache)
|
||||
m_option->cache->addFile(pro);
|
||||
}
|
||||
return pro;
|
||||
}
|
||||
|
||||
bool ProFileEvaluator::Private::evaluateFile(const QString &fileName)
|
||||
@@ -2803,10 +2855,10 @@ bool ProFileEvaluator::Private::evaluateFile(const QString &fileName)
|
||||
errorMessage(format("circular inclusion of %1").arg(fn));
|
||||
return false;
|
||||
}
|
||||
ProFile *pro = q->parsedProFile(fn);
|
||||
if (pro) {
|
||||
if (ProFile *pro = parsedProFile(fn, true)) {
|
||||
q->aboutToEval(pro);
|
||||
bool ok = (pro->Accept(this) == ProItem::ReturnTrue);
|
||||
q->releaseParsedProFile(pro);
|
||||
pro->deref();
|
||||
return ok;
|
||||
} else {
|
||||
return false;
|
||||
@@ -2857,12 +2909,13 @@ bool ProFileEvaluator::Private::evaluateFeatureFile(
|
||||
bool cumulative = m_cumulative;
|
||||
m_cumulative = false;
|
||||
|
||||
// Don't use evaluateFile() here to avoid the virtual parsedProFile().
|
||||
// Don't use evaluateFile() here to avoid calling aboutToEval().
|
||||
// The path is fully normalized already.
|
||||
ProFile pro(fn);
|
||||
bool ok = false;
|
||||
if (read(&pro))
|
||||
ok = (pro.Accept(this) == ProItem::ReturnTrue);
|
||||
if (ProFile *pro = parsedProFile(fn, true)) {
|
||||
ok = (pro->Accept(this) == ProItem::ReturnTrue);
|
||||
pro->deref();
|
||||
}
|
||||
|
||||
m_cumulative = cumulative;
|
||||
return ok;
|
||||
@@ -3019,14 +3072,9 @@ ProFileEvaluator::TemplateType ProFileEvaluator::templateType()
|
||||
return TT_Unknown;
|
||||
}
|
||||
|
||||
bool ProFileEvaluator::queryProFile(ProFile *pro)
|
||||
ProFile *ProFileEvaluator::parsedProFile(const QString &fileName, const QString &contents)
|
||||
{
|
||||
return d->read(pro);
|
||||
}
|
||||
|
||||
bool ProFileEvaluator::queryProFile(ProFile *pro, const QString &content)
|
||||
{
|
||||
return d->read(pro, content);
|
||||
return d->parsedProFile(fileName, false, contents);
|
||||
}
|
||||
|
||||
bool ProFileEvaluator::accept(ProFile *pro)
|
||||
@@ -3039,6 +3087,10 @@ QString ProFileEvaluator::propertyValue(const QString &name) const
|
||||
return d->propertyValue(name);
|
||||
}
|
||||
|
||||
void ProFileEvaluator::aboutToEval(ProFile *)
|
||||
{
|
||||
}
|
||||
|
||||
void ProFileEvaluator::logMessage(const QString &message)
|
||||
{
|
||||
qWarning("%s", qPrintable(message));
|
||||
|
@@ -42,6 +42,22 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
class ProFileOption;
|
||||
|
||||
class ProFileCache
|
||||
{
|
||||
public:
|
||||
ProFileCache() {}
|
||||
~ProFileCache();
|
||||
|
||||
void addFile(ProFile *pro);
|
||||
ProFile *getFile(const QString &fileName);
|
||||
|
||||
void discardFile(const QString &fileName);
|
||||
void discardFiles(const QString &prefix);
|
||||
|
||||
private:
|
||||
QHash<QString, ProFile *> parsed_files;
|
||||
};
|
||||
|
||||
class ProFileEvaluator
|
||||
{
|
||||
class Private;
|
||||
@@ -74,8 +90,8 @@ public:
|
||||
void setConfigCommandLineArguments(const QStringList &addUserConfigCmdArgs, const QStringList &removeUserConfigCmdArgs);
|
||||
void setParsePreAndPostFiles(bool on); // Default is true
|
||||
|
||||
bool queryProFile(ProFile *pro);
|
||||
bool queryProFile(ProFile *pro, const QString &content); // the same as above but the content is read from "content" string, not from filesystem
|
||||
// If contents is non-null, it will be used instead of the file's actual content
|
||||
ProFile *parsedProFile(const QString &fileName, const QString &contents = QString());
|
||||
bool accept(ProFile *pro);
|
||||
|
||||
QStringList values(const QString &variableName) const;
|
||||
@@ -87,8 +103,7 @@ public:
|
||||
QString propertyValue(const QString &val) const;
|
||||
|
||||
// for our descendents
|
||||
virtual ProFile *parsedProFile(const QString &fileName);
|
||||
virtual void releaseParsedProFile(ProFile *proFile);
|
||||
virtual void aboutToEval(ProFile *proFile); // only .pri, but not .prf. or .pro
|
||||
virtual void logMessage(const QString &msg);
|
||||
virtual void errorMessage(const QString &msg); // .pro parse errors
|
||||
virtual void fileMessage(const QString &msg); // error() and message() from .pro file
|
||||
@@ -130,6 +145,7 @@ struct ProFileOption
|
||||
QString qmakespec;
|
||||
QString cachefile;
|
||||
QHash<QString, QString> properties;
|
||||
ProFileCache *cache;
|
||||
|
||||
enum TARG_MODE { TARG_UNIX_MODE, TARG_WIN_MODE, TARG_MACX_MODE, TARG_MAC9_MODE, TARG_QNX6_MODE };
|
||||
TARG_MODE target_mode;
|
||||
|
Reference in New Issue
Block a user