qmlprofiler: Allow specification of features to record
Task-number: QTBUG-43066 Change-Id: I963a5a483f961dd150f00de3d96c723c8b62edb8 Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
This commit is contained in:
parent
08533d2659
commit
db69cd87d3
|
@ -59,6 +59,20 @@ static const char commandTextC[] =
|
|||
" Terminate the program if started from qmlprofiler,\n"
|
||||
" and qmlprofiler itself.";
|
||||
|
||||
static const char *features[] = {
|
||||
"javascript",
|
||||
"memory",
|
||||
"pixmapcache",
|
||||
"scenegraph",
|
||||
"animations",
|
||||
"painting",
|
||||
"compiling",
|
||||
"creating",
|
||||
"binding",
|
||||
"handlingsignal",
|
||||
"inputevents"
|
||||
};
|
||||
|
||||
static const char TraceFileExtension[] = ".qtd";
|
||||
|
||||
QmlProfilerApplication::QmlProfilerApplication(int &argc, char **argv) :
|
||||
|
@ -172,6 +186,26 @@ void QmlProfilerApplication::parseArguments()
|
|||
QLatin1String("on|off"), QLatin1String("on"));
|
||||
parser.addOption(record);
|
||||
|
||||
QStringList featureList;
|
||||
for (int i = 0; i < QQmlProfilerService::MaximumProfileFeature; ++i)
|
||||
featureList << QLatin1String(features[i]);
|
||||
|
||||
QCommandLineOption include(QLatin1String("include"),
|
||||
tr("Comma-separated list of features to record. By default all "
|
||||
"features supported by the QML engine are recorded. If --include "
|
||||
"is specified, only the given features will be recorded. "
|
||||
"The following features are unserstood by qmlprofiler: %1").arg(
|
||||
featureList.join(", ")),
|
||||
QLatin1String("feature,..."));
|
||||
parser.addOption(include);
|
||||
|
||||
QCommandLineOption exclude(QLatin1String("exclude"),
|
||||
tr("Comma-separated list of features to exclude when recording. By "
|
||||
"default all features supported by the QML engine are recorded. "
|
||||
"See --include for the features understood by qmlprofiler."),
|
||||
QLatin1String("feature,..."));
|
||||
parser.addOption(exclude);
|
||||
|
||||
QCommandLineOption interactive(QLatin1String("interactive"),
|
||||
tr("Manually control the recording from the command line. The "
|
||||
"profiler will not terminate itself when the application "
|
||||
|
@ -213,6 +247,23 @@ void QmlProfilerApplication::parseArguments()
|
|||
m_recording = (parser.value(record) == QLatin1String("on"));
|
||||
m_interactive = parser.isSet(interactive);
|
||||
|
||||
quint64 features = std::numeric_limits<quint64>::max();
|
||||
if (parser.isSet(include)) {
|
||||
if (parser.isSet(exclude)) {
|
||||
logError(tr("qmlprofiler can only process either --include or --exclude, not both."));
|
||||
parser.showHelp(4);
|
||||
}
|
||||
features = parseFeatures(featureList, parser.value(include), false);
|
||||
}
|
||||
|
||||
if (parser.isSet(exclude))
|
||||
features = parseFeatures(featureList, parser.value(exclude), true);
|
||||
|
||||
if (features == 0)
|
||||
parser.showHelp(4);
|
||||
|
||||
m_qmlProfilerClient.setFeatures(features);
|
||||
|
||||
if (parser.isSet(verbose))
|
||||
m_verbose = true;
|
||||
|
||||
|
@ -244,6 +295,27 @@ bool QmlProfilerApplication::isInteractive() const
|
|||
return m_interactive;
|
||||
}
|
||||
|
||||
quint64 QmlProfilerApplication::parseFeatures(const QStringList &featureList, const QString &values,
|
||||
bool exclude)
|
||||
{
|
||||
quint64 features = exclude ? std::numeric_limits<quint64>::max() : 0;
|
||||
QStringList givenFeatures = values.split(QLatin1Char(','));
|
||||
foreach (const QString &f, givenFeatures) {
|
||||
int index = featureList.indexOf(f);
|
||||
if (index < 0) {
|
||||
logError(tr("Unknown feature '%1'").arg(f));
|
||||
return 0;
|
||||
}
|
||||
quint64 flag = static_cast<quint64>(1) << index;
|
||||
features = (exclude ? (features ^ flag) : (features | flag));
|
||||
}
|
||||
if (features == 0) {
|
||||
logError(exclude ? tr("No features remaining to record after processing --exclude.") :
|
||||
tr("No features specified for --include."));
|
||||
}
|
||||
return features;
|
||||
}
|
||||
|
||||
void QmlProfilerApplication::flush()
|
||||
{
|
||||
if (m_recording) {
|
||||
|
|
|
@ -90,6 +90,7 @@ private slots:
|
|||
void v8Complete();
|
||||
|
||||
private:
|
||||
quint64 parseFeatures(const QStringList &featureList, const QString &values, bool exclude);
|
||||
bool checkOutputFile(PendingRequest pending);
|
||||
void flush();
|
||||
void output();
|
||||
|
|
|
@ -71,7 +71,7 @@ class QmlProfilerClientPrivate
|
|||
{
|
||||
public:
|
||||
QmlProfilerClientPrivate()
|
||||
: inProgressRanges(0)
|
||||
: inProgressRanges(0) , features(std::numeric_limits<quint64>::max())
|
||||
{
|
||||
::memset(rangeCount, 0,
|
||||
QQmlProfilerService::MaximumRangeType * sizeof(int));
|
||||
|
@ -83,6 +83,8 @@ public:
|
|||
QStack<QmlEventLocation> rangeLocations[QQmlProfilerService::MaximumRangeType];
|
||||
QStack<QQmlProfilerService::BindingType> bindingTypes;
|
||||
int rangeCount[QQmlProfilerService::MaximumRangeType];
|
||||
|
||||
quint64 features;
|
||||
};
|
||||
|
||||
QmlProfilerClient::QmlProfilerClient(
|
||||
|
@ -97,6 +99,11 @@ QmlProfilerClient::~QmlProfilerClient()
|
|||
delete d;
|
||||
}
|
||||
|
||||
void QmlProfilerClient::setFeatures(quint64 features)
|
||||
{
|
||||
d->features = features;
|
||||
}
|
||||
|
||||
void QmlProfilerClient::clearData()
|
||||
{
|
||||
::memset(d->rangeCount, 0,
|
||||
|
@ -109,15 +116,39 @@ void QmlProfilerClient::sendRecordingStatus(bool record)
|
|||
{
|
||||
QByteArray ba;
|
||||
QDataStream stream(&ba, QIODevice::WriteOnly);
|
||||
stream << record;
|
||||
stream << record << -1 << d->features;
|
||||
sendMessage(ba);
|
||||
}
|
||||
|
||||
inline QQmlProfilerService::ProfileFeature featureFromRangeType(
|
||||
QQmlProfilerService::RangeType range)
|
||||
{
|
||||
switch (range) {
|
||||
case QQmlProfilerService::Painting:
|
||||
return QQmlProfilerService::ProfilePainting;
|
||||
case QQmlProfilerService::Compiling:
|
||||
return QQmlProfilerService::ProfileCompiling;
|
||||
case QQmlProfilerService::Creating:
|
||||
return QQmlProfilerService::ProfileCreating;
|
||||
case QQmlProfilerService::Binding:
|
||||
return QQmlProfilerService::ProfileBinding;
|
||||
case QQmlProfilerService::HandlingSignal:
|
||||
return QQmlProfilerService::ProfileHandlingSignal;
|
||||
case QQmlProfilerService::Javascript:
|
||||
return QQmlProfilerService::ProfileJavaScript;
|
||||
default:
|
||||
return QQmlProfilerService::MaximumProfileFeature;
|
||||
}
|
||||
}
|
||||
|
||||
void QmlProfilerClient::messageReceived(const QByteArray &data)
|
||||
{
|
||||
QByteArray rwData = data;
|
||||
QDataStream stream(&rwData, QIODevice::ReadOnly);
|
||||
|
||||
// Force all the 1 << <FLAG> expressions to be done in 64 bit, to silence some warnings
|
||||
const quint64 one = static_cast<quint64>(1);
|
||||
|
||||
qint64 time;
|
||||
int messageType;
|
||||
|
||||
|
@ -133,6 +164,8 @@ void QmlProfilerClient::messageReceived(const QByteArray &data)
|
|||
if (event == QQmlProfilerService::EndTrace) {
|
||||
emit this->traceFinished(time);
|
||||
} else if (event == QQmlProfilerService::AnimationFrame) {
|
||||
if (!(d->features & one << QQmlProfilerService::ProfileAnimations))
|
||||
return;
|
||||
int frameRate, animationCount;
|
||||
int threadId = 0;
|
||||
stream >> frameRate >> animationCount;
|
||||
|
@ -149,6 +182,8 @@ void QmlProfilerClient::messageReceived(const QByteArray &data)
|
|||
} else if (messageType == QQmlProfilerService::Complete) {
|
||||
emit complete();
|
||||
} else if (messageType == QQmlProfilerService::SceneGraphFrame) {
|
||||
if (!(d->features & one << QQmlProfilerService::ProfileSceneGraph))
|
||||
return;
|
||||
int sgEventType;
|
||||
int count = 0;
|
||||
qint64 params[5];
|
||||
|
@ -162,6 +197,8 @@ void QmlProfilerClient::messageReceived(const QByteArray &data)
|
|||
emit sceneGraphFrame((QQmlProfilerService::SceneGraphFrameType)sgEventType, time,
|
||||
params[0], params[1], params[2], params[3], params[4]);
|
||||
} else if (messageType == QQmlProfilerService::PixmapCacheEvent) {
|
||||
if (!(d->features & one << QQmlProfilerService::ProfilePixmapCache))
|
||||
return;
|
||||
int pixEvTy, width = 0, height = 0, refcount = 0;
|
||||
QString pixUrl;
|
||||
stream >> pixEvTy >> pixUrl;
|
||||
|
@ -175,6 +212,8 @@ void QmlProfilerClient::messageReceived(const QByteArray &data)
|
|||
emit pixmapCache((QQmlProfilerService::PixmapEventType)pixEvTy, time,
|
||||
QmlEventLocation(pixUrl,0,0), width, height, refcount);
|
||||
} else if (messageType == QQmlProfilerService::MemoryAllocation) {
|
||||
if (!(d->features & one << QQmlProfilerService::ProfileMemory))
|
||||
return;
|
||||
int type;
|
||||
qint64 delta;
|
||||
stream >> type >> delta;
|
||||
|
@ -186,6 +225,10 @@ void QmlProfilerClient::messageReceived(const QByteArray &data)
|
|||
if (range >= QQmlProfilerService::MaximumRangeType)
|
||||
return;
|
||||
|
||||
if (!(d->features & one << featureFromRangeType(
|
||||
static_cast<QQmlProfilerService::RangeType>(range))))
|
||||
return;
|
||||
|
||||
if (messageType == QQmlProfilerService::RangeStart) {
|
||||
d->rangeStartTimes[range].push(time);
|
||||
d->inProgressRanges |= (static_cast<qint64>(1) << range);
|
||||
|
|
|
@ -74,6 +74,8 @@ public:
|
|||
QmlProfilerClient(QQmlDebugConnection *client);
|
||||
~QmlProfilerClient();
|
||||
|
||||
void setFeatures(quint64 features);
|
||||
|
||||
public slots:
|
||||
void clearData();
|
||||
void sendRecordingStatus(bool record);
|
||||
|
|
Loading…
Reference in New Issue