Add -profile option that dumps plugin load/initialization times.

Reviewed-by: con
This commit is contained in:
Friedemann Kleint
2010-03-02 12:33:51 +01:00
parent ab3a702c07
commit eae2f62970
5 changed files with 82 additions and 11 deletions

View File

@@ -34,9 +34,10 @@
using namespace ExtensionSystem; using namespace ExtensionSystem;
using namespace ExtensionSystem::Internal; using namespace ExtensionSystem::Internal;
static const char *END_OF_OPTIONS = "--"; static const char END_OF_OPTIONS[] = "--";
const char *OptionsParser::NO_LOAD_OPTION = "-noload"; const char *OptionsParser::NO_LOAD_OPTION = "-noload";
const char *OptionsParser::TEST_OPTION = "-test"; const char *OptionsParser::TEST_OPTION = "-test";
const char *OptionsParser::PROFILE_OPTION = "-profile";
OptionsParser::OptionsParser(const QStringList &args, OptionsParser::OptionsParser(const QStringList &args,
const QMap<QString, bool> &appOptions, const QMap<QString, bool> &appOptions,
@@ -69,6 +70,8 @@ bool OptionsParser::parse()
break; break;
if (checkForNoLoadOption()) if (checkForNoLoadOption())
continue; continue;
if (checkForProfilingOption())
continue;
if (checkForTestOption()) if (checkForTestOption())
continue; continue;
if (checkForAppOption()) if (checkForAppOption())
@@ -148,6 +151,14 @@ bool OptionsParser::checkForAppOption()
return true; return true;
} }
bool OptionsParser::checkForProfilingOption()
{
if (m_currentArg != QLatin1String(PROFILE_OPTION))
return false;
m_pmPrivate->initProfiling();
return true;
}
bool OptionsParser::checkForPluginOption() bool OptionsParser::checkForPluginOption()
{ {
bool requiresParameter; bool requiresParameter;

View File

@@ -51,6 +51,7 @@ public:
static const char *NO_LOAD_OPTION; static const char *NO_LOAD_OPTION;
static const char *TEST_OPTION; static const char *TEST_OPTION;
static const char *PROFILE_OPTION;
private: private:
// return value indicates if the option was processed // return value indicates if the option was processed
// it doesn't indicate success (--> m_hasError) // it doesn't indicate success (--> m_hasError)
@@ -59,6 +60,7 @@ private:
bool checkForTestOption(); bool checkForTestOption();
bool checkForAppOption(); bool checkForAppOption();
bool checkForPluginOption(); bool checkForPluginOption();
bool checkForProfilingOption();
bool checkForUnknownOption(); bool checkForUnknownOption();
enum TokenType { OptionalToken, RequiredToken }; enum TokenType { OptionalToken, RequiredToken };

View File

@@ -38,6 +38,8 @@
#include <QtCore/QDir> #include <QtCore/QDir>
#include <QtCore/QTextStream> #include <QtCore/QTextStream>
#include <QtCore/QWriteLocker> #include <QtCore/QWriteLocker>
#include <QtCore/QTime>
#include <QtCore/QDateTime>
#include <QtDebug> #include <QtDebug>
#ifdef WITH_TESTS #ifdef WITH_TESTS
#include <QTest> #include <QTest>
@@ -465,6 +467,9 @@ void PluginManager::formatOptions(QTextStream &str, int optionIndentation, int d
formatOption(str, QLatin1String(OptionsParser::NO_LOAD_OPTION), formatOption(str, QLatin1String(OptionsParser::NO_LOAD_OPTION),
QLatin1String("plugin"), QLatin1String("Do not load <plugin>"), QLatin1String("plugin"), QLatin1String("Do not load <plugin>"),
optionIndentation, descriptionIndentation); optionIndentation, descriptionIndentation);
formatOption(str, QLatin1String(OptionsParser::PROFILE_OPTION),
QString(), QLatin1String("Profile plugin loading"),
optionIndentation, descriptionIndentation);
} }
/*! /*!
@@ -573,8 +578,10 @@ PluginSpecPrivate *PluginManagerPrivate::privateSpec(PluginSpec *spec)
\fn PluginManagerPrivate::PluginManagerPrivate(PluginManager *pluginManager) \fn PluginManagerPrivate::PluginManagerPrivate(PluginManager *pluginManager)
\internal \internal
*/ */
PluginManagerPrivate::PluginManagerPrivate(PluginManager *pluginManager) PluginManagerPrivate::PluginManagerPrivate(PluginManager *pluginManager) :
: extension("xml"), q(pluginManager) extension(QLatin1String("xml")),
m_profileElapsedMS(0),
q(pluginManager)
{ {
} }
@@ -740,14 +747,19 @@ void PluginManagerPrivate::loadPlugin(PluginSpec *spec, PluginSpec::State destSt
{ {
if (spec->hasError()) if (spec->hasError())
return; return;
if (destState == PluginSpec::Running) { switch (destState) {
case PluginSpec::Running:
profilingReport(">initializeExtensions", spec);
spec->d->initializeExtensions(); spec->d->initializeExtensions();
profilingReport("<initializeExtensions", spec);
return; return;
} else if (destState == PluginSpec::Deleted) { case PluginSpec::Deleted:
spec->d->kill(); spec->d->kill();
return; return;
default:
break;
} }
foreach (PluginSpec *depSpec, spec->dependencySpecs()) { foreach (const PluginSpec *depSpec, spec->dependencySpecs()) {
if (depSpec->state() != destState) { if (depSpec->state() != destState) {
spec->d->hasError = true; spec->d->hasError = true;
spec->d->errorString = spec->d->errorString =
@@ -756,12 +768,25 @@ void PluginManagerPrivate::loadPlugin(PluginSpec *spec, PluginSpec::State destSt
return; return;
} }
} }
if (destState == PluginSpec::Loaded) switch (destState) {
case PluginSpec::Loaded:
profilingReport(">loadLibrary", spec);
spec->d->loadLibrary(); spec->d->loadLibrary();
else if (destState == PluginSpec::Initialized) profilingReport("<loadLibrary", spec);
break;
case PluginSpec::Initialized:
profilingReport(">initializePlugin", spec);
spec->d->initializePlugin(); spec->d->initializePlugin();
else if (destState == PluginSpec::Stopped) profilingReport("<initializePlugin", spec);
break;
case PluginSpec::Stopped:
profilingReport(">stop", spec);
spec->d->stop(); spec->d->stop();
profilingReport("<stop", spec);
break;
default:
break;
}
} }
/*! /*!
@@ -787,7 +812,8 @@ void PluginManagerPrivate::readPluginPaths()
QStringList searchPaths = pluginPaths; QStringList searchPaths = pluginPaths;
while (!searchPaths.isEmpty()) { while (!searchPaths.isEmpty()) {
const QDir dir(searchPaths.takeFirst()); const QDir dir(searchPaths.takeFirst());
const QFileInfoList files = dir.entryInfoList(QStringList() << QString("*.%1").arg(extension), QDir::Files); const QString pattern = QLatin1String("*.") + extension;
const QFileInfoList files = dir.entryInfoList(QStringList(pattern), QDir::Files);
foreach (const QFileInfo &file, files) foreach (const QFileInfo &file, files)
specFiles << file.absoluteFilePath(); specFiles << file.absoluteFilePath();
const QFileInfoList dirs = dir.entryInfoList(QDir::Dirs|QDir::NoDotAndDotDot); const QFileInfoList dirs = dir.entryInfoList(QDir::Dirs|QDir::NoDotAndDotDot);
@@ -844,3 +870,26 @@ PluginSpec *PluginManagerPrivate::pluginByName(const QString &name) const
return 0; return 0;
} }
void PluginManagerPrivate::initProfiling()
{
if (m_profileTimer.isNull()) {
m_profileTimer.reset(new QTime);
m_profileTimer->start();
m_profileElapsedMS = 0;
qDebug("Profiling started");
}
}
void PluginManagerPrivate::profilingReport(const char *what, const PluginSpec *spec /* = 0 */)
{
if (!m_profileTimer.isNull()) {
const int absoluteElapsedMS = m_profileTimer->elapsed();
const int elapsedMS = absoluteElapsedMS - m_profileElapsedMS;
m_profileElapsedMS = absoluteElapsedMS;
if (spec) {
qDebug("%-22s %-22s %8dms (%8dms)", what, qPrintable(spec->name()), absoluteElapsedMS, elapsedMS);
} else {
qDebug("%-22s %8dms (%8dms)", what, absoluteElapsedMS, elapsedMS);
}
}
}

View File

@@ -36,6 +36,11 @@
#include <QtCore/QSet> #include <QtCore/QSet>
#include <QtCore/QStringList> #include <QtCore/QStringList>
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtCore/QScopedPointer>
QT_BEGIN_NAMESPACE
class QTime;
QT_END_NAMESPACE
namespace ExtensionSystem { namespace ExtensionSystem {
@@ -61,6 +66,8 @@ public:
QList<PluginSpec *> loadQueue(); QList<PluginSpec *> loadQueue();
void loadPlugin(PluginSpec *spec, PluginSpec::State destState); void loadPlugin(PluginSpec *spec, PluginSpec::State destState);
void resolveDependencies(); void resolveDependencies();
void initProfiling();
void profilingReport(const char *what, const PluginSpec *spec = 0);
QList<PluginSpec *> pluginSpecs; QList<PluginSpec *> pluginSpecs;
QList<PluginSpec *> testSpecs; QList<PluginSpec *> testSpecs;
@@ -69,6 +76,8 @@ public:
QList<QObject *> allObjects; // ### make this a QList<QPointer<QObject> > > ? QList<QObject *> allObjects; // ### make this a QList<QPointer<QObject> > > ?
QStringList arguments; QStringList arguments;
QScopedPointer<QTime> m_profileTimer;
int m_profileElapsedMS;
// Look in argument descriptions of the specs for the option. // Look in argument descriptions of the specs for the option.
PluginSpec *pluginForOption(const QString &option, bool *requiresArgument) const; PluginSpec *pluginForOption(const QString &option, bool *requiresArgument) const;

View File

@@ -734,7 +734,7 @@ bool PluginSpecPrivate::resolveDependencies(const QList<PluginSpec *> &specs)
if (!found) { if (!found) {
hasError = true; hasError = true;
if (!errorString.isEmpty()) if (!errorString.isEmpty())
errorString.append("\n"); errorString.append(QLatin1Char('\n'));
errorString.append(QCoreApplication::translate("PluginSpec", "Could not resolve dependency '%1(%2)'") errorString.append(QCoreApplication::translate("PluginSpec", "Could not resolve dependency '%1(%2)'")
.arg(dependency.name).arg(dependency.version)); .arg(dependency.name).arg(dependency.version));
continue; continue;