aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/qmlprofiler/qmlprofilerapplication.cpp57
-rw-r--r--tools/qmlprofiler/qmlprofilerapplication.h6
-rw-r--r--tools/qmlprofiler/qmlprofilerclient.cpp141
-rw-r--r--tools/qmlprofiler/qmlprofilerclient.h21
-rw-r--r--tools/qmlprofiler/qmlprofilerdata.cpp727
-rw-r--r--tools/qmlprofiler/qmlprofilerdata.h23
6 files changed, 387 insertions, 588 deletions
diff --git a/tools/qmlprofiler/qmlprofilerapplication.cpp b/tools/qmlprofiler/qmlprofilerapplication.cpp
index 033492b516..0b0417bd7d 100644
--- a/tools/qmlprofiler/qmlprofilerapplication.cpp
+++ b/tools/qmlprofiler/qmlprofilerapplication.cpp
@@ -83,24 +83,27 @@ QmlProfilerApplication::QmlProfilerApplication(int &argc, char **argv) :
m_verbose(false),
m_recording(true),
m_interactive(false),
- m_qmlProfilerClient(&m_connection, &m_profilerData),
m_connectionAttempts(0)
{
+ m_connection.reset(new QQmlDebugConnection);
+ m_profilerData.reset(new QmlProfilerData);
+ m_qmlProfilerClient.reset(new QmlProfilerClient(m_connection.data(), m_profilerData.data()));
m_connectTimer.setInterval(1000);
connect(&m_connectTimer, &QTimer::timeout, this, &QmlProfilerApplication::tryToConnect);
- connect(&m_connection, &QQmlDebugConnection::connected,
+ connect(m_connection.data(), &QQmlDebugConnection::connected,
this, &QmlProfilerApplication::connected);
- connect(&m_qmlProfilerClient, &QmlProfilerClient::enabledChanged,
+ connect(m_qmlProfilerClient.data(), &QmlProfilerClient::enabledChanged,
this, &QmlProfilerApplication::traceClientEnabledChanged);
- connect(&m_qmlProfilerClient, &QmlProfilerClient::recordingStarted,
+ connect(m_qmlProfilerClient.data(), &QmlProfilerClient::traceStarted,
this, &QmlProfilerApplication::notifyTraceStarted);
- connect(&m_qmlProfilerClient, &QmlProfilerClient::error,
+ connect(m_qmlProfilerClient.data(), &QmlProfilerClient::error,
this, &QmlProfilerApplication::logError);
- connect(&m_profilerData, &QmlProfilerData::error, this, &QmlProfilerApplication::logError);
- connect(&m_profilerData, &QmlProfilerData::dataReady,
+ connect(m_profilerData.data(), &QmlProfilerData::error,
+ this, &QmlProfilerApplication::logError);
+ connect(m_profilerData.data(), &QmlProfilerData::dataReady,
this, &QmlProfilerApplication::traceFinished);
}
@@ -239,7 +242,7 @@ void QmlProfilerApplication::parseArguments()
if (features == 0)
parser.showHelp(4);
- m_qmlProfilerClient.setFeatures(features);
+ m_qmlProfilerClient->setRequestedFeatures(features);
if (parser.isSet(verbose))
m_verbose = true;
@@ -295,10 +298,10 @@ void QmlProfilerApplication::flush()
{
if (m_recording) {
m_pendingRequest = REQUEST_FLUSH;
- m_qmlProfilerClient.sendRecordingStatus(false);
+ m_qmlProfilerClient->sendRecordingStatus(false);
} else {
- if (m_profilerData.save(m_interactiveOutputFile)) {
- m_profilerData.clear();
+ if (m_profilerData->save(m_interactiveOutputFile)) {
+ m_profilerData->clear();
if (!m_interactiveOutputFile.isEmpty())
prompt(tr("Data written to %1.").arg(m_interactiveOutputFile));
else
@@ -313,7 +316,7 @@ void QmlProfilerApplication::flush()
void QmlProfilerApplication::output()
{
- if (m_profilerData.save(m_interactiveOutputFile)) {
+ if (m_profilerData->save(m_interactiveOutputFile)) {
if (!m_interactiveOutputFile.isEmpty())
prompt(tr("Data written to %1.").arg(m_interactiveOutputFile));
else
@@ -385,12 +388,12 @@ void QmlProfilerApplication::userCommand(const QString &command)
if (cmd == Constants::CMD_RECORD || cmd == Constants::CMD_RECORD2) {
m_pendingRequest = REQUEST_TOGGLE_RECORDING;
- m_qmlProfilerClient.sendRecordingStatus(!m_recording);
+ m_qmlProfilerClient->sendRecordingStatus(!m_recording);
} else if (cmd == Constants::CMD_QUIT || cmd == Constants::CMD_QUIT2) {
m_pendingRequest = REQUEST_QUIT;
if (m_recording) {
prompt(tr("The application is still generating data. Really quit (y/n)?"));
- } else if (!m_profilerData.isEmpty()) {
+ } else if (!m_profilerData->isEmpty()) {
prompt(tr("There is still trace data in memory. Really quit (y/n)?"));
} else {
quit();
@@ -398,7 +401,7 @@ void QmlProfilerApplication::userCommand(const QString &command)
} else if (cmd == Constants::CMD_OUTPUT || cmd == Constants::CMD_OUTPUT2) {
if (m_recording) {
prompt(tr("Cannot output while recording data."));
- } else if (m_profilerData.isEmpty()) {
+ } else if (m_profilerData->isEmpty()) {
prompt(tr("No data was recorded so far."));
} else {
m_interactiveOutputFile = args.length() > 0 ? args.at(0).toString() : m_outputFile;
@@ -408,14 +411,14 @@ void QmlProfilerApplication::userCommand(const QString &command)
} else if (cmd == Constants::CMD_CLEAR || cmd == Constants::CMD_CLEAR2) {
if (m_recording) {
prompt(tr("Cannot clear data while recording."));
- } else if (m_profilerData.isEmpty()) {
+ } else if (m_profilerData->isEmpty()) {
prompt(tr("No data was recorded so far."));
} else {
- m_profilerData.clear();
+ m_profilerData->clear();
prompt(tr("Trace data cleared."));
}
} else if (cmd == Constants::CMD_FLUSH || cmd == Constants::CMD_FLUSH2) {
- if (!m_recording && m_profilerData.isEmpty()) {
+ if (!m_recording && m_profilerData->isEmpty()) {
prompt(tr("No data was recorded so far."));
} else {
m_interactiveOutputFile = args.length() > 0 ? args.at(0).toString() : m_outputFile;
@@ -443,9 +446,9 @@ void QmlProfilerApplication::notifyTraceStarted()
void QmlProfilerApplication::outputData()
{
- if (!m_profilerData.isEmpty()) {
- m_profilerData.save(m_outputFile);
- m_profilerData.clear();
+ if (!m_profilerData->isEmpty()) {
+ m_profilerData->save(m_outputFile);
+ m_profilerData->clear();
}
}
@@ -454,7 +457,7 @@ void QmlProfilerApplication::run()
if (m_runMode == LaunchMode) {
if (!m_socketFile.isEmpty()) {
logStatus(QString::fromLatin1("Listening on %1 ...").arg(m_socketFile));
- m_connection.startLocalServer(m_socketFile);
+ m_connection->startLocalServer(m_socketFile);
}
m_process = new QProcess(this);
QStringList arguments;
@@ -481,7 +484,7 @@ void QmlProfilerApplication::run()
void QmlProfilerApplication::tryToConnect()
{
- Q_ASSERT(!m_connection.isConnected());
+ Q_ASSERT(!m_connection->isConnected());
++ m_connectionAttempts;
if (!m_verbose && !(m_connectionAttempts % 5)) {// print every 5 seconds
@@ -497,7 +500,7 @@ void QmlProfilerApplication::tryToConnect()
if (m_socketFile.isEmpty()) {
logStatus(QString::fromLatin1("Connecting to %1:%2 ...").arg(m_hostName).arg(m_port));
- m_connection.connectToHost(m_hostName, m_port);
+ m_connection->connectToHost(m_hostName, m_port);
}
}
@@ -538,7 +541,7 @@ void QmlProfilerApplication::processFinished()
if (!m_interactive)
exit(exitCode);
else
- m_qmlProfilerClient.clearPendingData();
+ m_qmlProfilerClient->clearAll();
}
void QmlProfilerApplication::traceClientEnabledChanged(bool enabled)
@@ -547,7 +550,7 @@ void QmlProfilerApplication::traceClientEnabledChanged(bool enabled)
logStatus("Trace client is attached.");
// blocked server is waiting for recording message from both clients
// once the last one is connected, both messages should be sent
- m_qmlProfilerClient.sendRecordingStatus(m_recording);
+ m_qmlProfilerClient->setRecording(m_recording);
}
}
@@ -564,7 +567,7 @@ void QmlProfilerApplication::traceFinished()
prompt(tr("Application stopped recording."), false);
}
- m_qmlProfilerClient.clearPendingData();
+ m_qmlProfilerClient->clearEvents();
}
void QmlProfilerApplication::prompt(const QString &line, bool ready)
diff --git a/tools/qmlprofiler/qmlprofilerapplication.h b/tools/qmlprofiler/qmlprofilerapplication.h
index 13f0f041f0..f7a8efd61b 100644
--- a/tools/qmlprofiler/qmlprofilerapplication.h
+++ b/tools/qmlprofiler/qmlprofilerapplication.h
@@ -105,9 +105,9 @@ private:
bool m_recording;
bool m_interactive;
- QQmlDebugConnection m_connection;
- QmlProfilerClient m_qmlProfilerClient;
- QmlProfilerData m_profilerData;
+ QScopedPointer<QQmlDebugConnection> m_connection;
+ QScopedPointer<QmlProfilerClient> m_qmlProfilerClient;
+ QScopedPointer<QmlProfilerData> m_profilerData;
QTimer m_connectTimer;
uint m_connectionAttempts;
};
diff --git a/tools/qmlprofiler/qmlprofilerclient.cpp b/tools/qmlprofiler/qmlprofilerclient.cpp
index 0c031db914..b69c7e73e1 100644
--- a/tools/qmlprofiler/qmlprofilerclient.cpp
+++ b/tools/qmlprofiler/qmlprofilerclient.cpp
@@ -43,36 +43,26 @@ public:
QmlProfilerClientPrivate(QQmlDebugConnection *connection, QmlProfilerData *data);
QmlProfilerData *data;
-
- qint64 inProgressRanges;
- QStack<qint64> rangeStartTimes[QQmlProfilerDefinitions::MaximumRangeType];
- QStack<QStringList> rangeDatas[QQmlProfilerDefinitions::MaximumRangeType];
- QStack<QQmlEventLocation> rangeLocations[QQmlProfilerDefinitions::MaximumRangeType];
- int rangeCount[QQmlProfilerDefinitions::MaximumRangeType];
-
bool enabled;
};
QmlProfilerClientPrivate::QmlProfilerClientPrivate(QQmlDebugConnection *connection,
QmlProfilerData *data) :
- QQmlProfilerClientPrivate(connection), data(data), inProgressRanges(0), enabled(false)
+ QQmlProfilerClientPrivate(connection, data), data(data), enabled(false)
{
- ::memset(rangeCount, 0, QQmlProfilerDefinitions::MaximumRangeType * sizeof(int));
}
QmlProfilerClient::QmlProfilerClient(QQmlDebugConnection *connection, QmlProfilerData *data) :
QQmlProfilerClient(*(new QmlProfilerClientPrivate(connection, data)))
{
-}
-
-void QmlProfilerClient::clearPendingData()
-{
Q_D(QmlProfilerClient);
- for (int i = 0; i < QQmlProfilerDefinitions::MaximumRangeType; ++i) {
- d->rangeCount[i] = 0;
- d->rangeDatas[i].clear();
- d->rangeLocations[i].clear();
- }
+ setRequestedFeatures(std::numeric_limits<quint64>::max());
+ connect(this, &QQmlProfilerClient::traceStarted,
+ d->data, &QmlProfilerData::setTraceStartTime);
+ connect(this, &QQmlProfilerClient::traceFinished,
+ d->data, &QmlProfilerData::setTraceEndTime);
+ connect(this, &QQmlProfilerClient::complete,
+ d->data, &QmlProfilerData::complete);
}
void QmlProfilerClient::stateChanged(State state)
@@ -84,119 +74,4 @@ void QmlProfilerClient::stateChanged(State state)
}
}
-void QmlProfilerClient::traceStarted(qint64 time, int engineId)
-{
- Q_UNUSED(engineId);
- Q_D(QmlProfilerClient);
- d->data->setTraceStartTime(time);
- emit recordingStarted();
-}
-
-void QmlProfilerClient::traceFinished(qint64 time, int engineId)
-{
- Q_UNUSED(engineId);
- Q_D(QmlProfilerClient);
- d->data->setTraceEndTime(time);
-}
-
-void QmlProfilerClient::rangeStart(QQmlProfilerDefinitions::RangeType type, qint64 startTime)
-{
- Q_D(QmlProfilerClient);
- d->rangeStartTimes[type].push(startTime);
- d->inProgressRanges |= (static_cast<qint64>(1) << type);
- ++d->rangeCount[type];
-}
-
-void QmlProfilerClient::rangeData(QQmlProfilerDefinitions::RangeType type, qint64 time,
- const QString &data)
-{
- Q_UNUSED(time);
- Q_D(QmlProfilerClient);
- int count = d->rangeCount[type];
- if (count > 0) {
- while (d->rangeDatas[type].count() < count)
- d->rangeDatas[type].push(QStringList());
- d->rangeDatas[type][count - 1] << data;
- }
-}
-
-void QmlProfilerClient::rangeLocation(QQmlProfilerDefinitions::RangeType type, qint64 time,
- const QQmlEventLocation &location)
-{
- Q_UNUSED(time);
- Q_D(QmlProfilerClient);
- if (d->rangeCount[type] > 0)
- d->rangeLocations[type].push(location);
-}
-
-void QmlProfilerClient::rangeEnd(QQmlProfilerDefinitions::RangeType type, qint64 endTime)
-{
- Q_D(QmlProfilerClient);
-
- if (d->rangeCount[type] == 0) {
- emit error(tr("Spurious range end detected."));
- return;
- }
-
- --d->rangeCount[type];
- if (d->inProgressRanges & (static_cast<qint64>(1) << type))
- d->inProgressRanges &= ~(static_cast<qint64>(1) << type);
- QStringList data = d->rangeDatas[type].count() ? d->rangeDatas[type].pop() : QStringList();
- QQmlEventLocation location = d->rangeLocations[type].count() ? d->rangeLocations[type].pop() :
- QQmlEventLocation();
- qint64 startTime = d->rangeStartTimes[type].pop();
-
- if (d->rangeCount[type] == 0 && d->rangeDatas[type].count() + d->rangeStartTimes[type].count()
- + d->rangeLocations[type].count() != 0) {
- emit error(tr("Incorrectly nested range data"));
- return;
- }
-
- d->data->addQmlEvent(type, QQmlProfilerDefinitions::QmlBinding, startTime, endTime - startTime,
- data, location);
-}
-
-void QmlProfilerClient::animationFrame(qint64 time, int frameRate, int animationCount, int threadId)
-{
- Q_D(QmlProfilerClient);
- d->data->addFrameEvent(time, frameRate, animationCount, threadId);
-}
-
-void QmlProfilerClient::sceneGraphEvent(QQmlProfilerDefinitions::SceneGraphFrameType type,
- qint64 time, qint64 numericData1, qint64 numericData2,
- qint64 numericData3, qint64 numericData4,
- qint64 numericData5)
-{
- Q_D(QmlProfilerClient);
- d->data->addSceneGraphFrameEvent(type, time, numericData1, numericData2, numericData3,
- numericData4, numericData5);
-}
-
-void QmlProfilerClient::pixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventType type, qint64 time,
- const QString &url, int numericData1, int numericData2)
-{
- Q_D(QmlProfilerClient);
- d->data->addPixmapCacheEvent(type, time, url, numericData1, numericData2);
-}
-
-void QmlProfilerClient::memoryAllocation(QQmlProfilerDefinitions::MemoryType type, qint64 time,
- qint64 amount)
-{
- Q_D(QmlProfilerClient);
- d->data->addMemoryEvent(type, time, amount);
-}
-
-void QmlProfilerClient::inputEvent(QQmlProfilerDefinitions::InputEventType type, qint64 time,
- int a, int b)
-{
- Q_D(QmlProfilerClient);
- d->data->addInputEvent(type, time, a, b);
-}
-
-void QmlProfilerClient::complete()
-{
- Q_D(QmlProfilerClient);
- d->data->complete();
-}
-
#include "moc_qmlprofilerclient.cpp"
diff --git a/tools/qmlprofiler/qmlprofilerclient.h b/tools/qmlprofiler/qmlprofilerclient.h
index a04a412bb0..b9d8ce241f 100644
--- a/tools/qmlprofiler/qmlprofilerclient.h
+++ b/tools/qmlprofiler/qmlprofilerclient.h
@@ -29,9 +29,9 @@
#ifndef QMLPROFILERCLIENT_H
#define QMLPROFILERCLIENT_H
-#include <private/qqmleventlocation_p.h>
#include <private/qqmlprofilerclient_p.h>
#include <private/qqmlprofilerdefinitions_p.h>
+#include <private/qqmlprofilereventlocation_p.h>
class QmlProfilerData;
class QmlProfilerClientPrivate;
@@ -42,32 +42,13 @@ class QmlProfilerClient : public QQmlProfilerClient
public:
QmlProfilerClient(QQmlDebugConnection *connection, QmlProfilerData *data);
- void clearPendingData();
signals:
void enabledChanged(bool enabled);
- void recordingStarted();
void error(const QString &error);
private:
void stateChanged(State state) override;
-
- void traceStarted(qint64 time, int engineId) override;
- void traceFinished(qint64 time, int engineId) override;
- void rangeStart(QQmlProfilerDefinitions::RangeType type, qint64 startTime) override;
- void rangeData(QQmlProfilerDefinitions::RangeType type, qint64 time, const QString &data) override;
- void rangeLocation(QQmlProfilerDefinitions::RangeType type, qint64 time,
- const QQmlEventLocation &location) override;
- void rangeEnd(QQmlProfilerDefinitions::RangeType type, qint64 endTime) override;
- void animationFrame(qint64 time, int frameRate, int animationCount, int threadId) override;
- void sceneGraphEvent(QQmlProfilerDefinitions::SceneGraphFrameType type, qint64 time,
- qint64 numericData1, qint64 numericData2, qint64 numericData3,
- qint64 numericData4, qint64 numericData5) override;
- void pixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventType type, qint64 time,
- const QString &url, int numericData1, int numericData2) override;
- void memoryAllocation(QQmlProfilerDefinitions::MemoryType type, qint64 time, qint64 amount) override;
- void inputEvent(QQmlProfilerDefinitions::InputEventType type, qint64 time, int a, int b) override;
- void complete() override;
};
#endif // QMLPROFILERCLIENT_H
diff --git a/tools/qmlprofiler/qmlprofilerdata.cpp b/tools/qmlprofiler/qmlprofilerdata.cpp
index 7dcfa4cdaa..32e03298da 100644
--- a/tools/qmlprofiler/qmlprofilerdata.cpp
+++ b/tools/qmlprofiler/qmlprofilerdata.cpp
@@ -34,6 +34,8 @@
#include <QFile>
#include <QXmlStreamReader>
#include <QRegularExpression>
+#include <QQueue>
+#include <QStack>
#include <limits>
@@ -60,72 +62,13 @@ static const char *MESSAGE_STRINGS[] = {
"Complete",
"PixmapCache",
"SceneGraph",
- "MemoryAllocation"
+ "MemoryAllocation",
+ "DebugMessage"
};
Q_STATIC_ASSERT(sizeof(MESSAGE_STRINGS) ==
QQmlProfilerDefinitions::MaximumMessage * sizeof(const char *));
-struct QmlRangeEventData {
- QmlRangeEventData() {} // never called
- QmlRangeEventData(const QString &_displayName, int _detailType, const QString &_eventHashStr,
- const QQmlEventLocation &_location, const QString &_details,
- QQmlProfilerDefinitions::Message _message,
- QQmlProfilerDefinitions::RangeType _rangeType)
- : displayName(_displayName), eventHashStr(_eventHashStr), location(_location),
- details(_details), message(_message), rangeType(_rangeType), detailType(_detailType) {}
- QString displayName;
- QString eventHashStr;
- QQmlEventLocation location;
- QString details;
- QQmlProfilerDefinitions::Message message;
- QQmlProfilerDefinitions::RangeType rangeType;
- int detailType; // can be BindingType, PixmapCacheEventType or SceneGraphFrameType
-};
-
-struct QmlRangeEventStartInstance {
- QmlRangeEventStartInstance() {} // never called
- QmlRangeEventStartInstance(qint64 _startTime, qint64 _duration, int _frameRate,
- int _animationCount, int _threadId, QmlRangeEventData *_data)
- : startTime(_startTime), duration(_duration), frameRate(_frameRate),
- animationCount(_animationCount), threadId(_threadId), numericData4(-1), numericData5(-1),
- data(_data)
- { }
-
- QmlRangeEventStartInstance(qint64 _startTime, qint64 _numericData1, qint64 _numericData2,
- qint64 _numericData3, qint64 _numericData4, qint64 _numericData5,
- QmlRangeEventData *_data)
- : startTime(_startTime), duration(-1), numericData1(_numericData1),
- numericData2(_numericData2), numericData3(_numericData3), numericData4(_numericData4),
- numericData5(_numericData5), data(_data)
- { }
- qint64 startTime;
- qint64 duration;
- union {
- int frameRate;
- int inputType;
- qint64 numericData1;
- };
- union {
- int animationCount;
- int inputA;
- qint64 numericData2;
- };
- union {
- int threadId;
- int inputB;
- qint64 numericData3;
- };
- qint64 numericData4;
- qint64 numericData5;
- QmlRangeEventData *data;
-};
-
-QT_BEGIN_NAMESPACE
-Q_DECLARE_TYPEINFO(QmlRangeEventData, Q_MOVABLE_TYPE);
-Q_DECLARE_TYPEINFO(QmlRangeEventStartInstance, Q_MOVABLE_TYPE);
-QT_END_NAMESPACE
-
/////////////////////////////////////////////////////////////////
class QmlProfilerDataPrivate
{
@@ -133,8 +76,8 @@ public:
QmlProfilerDataPrivate(QmlProfilerData *qq){ Q_UNUSED(qq); }
// data storage
- QHash<QString, QmlRangeEventData *> eventDescriptions;
- QVector<QmlRangeEventStartInstance> startInstanceList;
+ QVector<QQmlProfilerEventType> eventTypes;
+ QVector<QQmlProfilerEvent> events;
qint64 traceStartTime;
qint64 traceEndTime;
@@ -146,7 +89,7 @@ public:
/////////////////////////////////////////////////////////////////
QmlProfilerData::QmlProfilerData(QObject *parent) :
- QObject(parent),d(new QmlProfilerDataPrivate(this))
+ QQmlProfilerEventReceiver(parent), d(new QmlProfilerDataPrivate(this))
{
d->state = Empty;
clear();
@@ -160,9 +103,8 @@ QmlProfilerData::~QmlProfilerData()
void QmlProfilerData::clear()
{
- qDeleteAll(d->eventDescriptions);
- d->eventDescriptions.clear();
- d->startInstanceList.clear();
+ d->eventTypes.clear();
+ d->events.clear();
d->traceEndTime = std::numeric_limits<qint64>::min();
d->traceStartTime = std::numeric_limits<qint64>::max();
@@ -171,15 +113,6 @@ void QmlProfilerData::clear()
setState(Empty);
}
-QString QmlProfilerData::getHashStringForQmlEvent(const QQmlEventLocation &location, int eventType)
-{
- return QString(QStringLiteral("%1:%2:%3:%4")).arg(
- location.filename,
- QString::number(location.line),
- QString::number(location.column),
- QString::number(eventType));
-}
-
QString QmlProfilerData::qmlRangeTypeAsString(QQmlProfilerDefinitions::RangeType type)
{
if (type * sizeof(char *) < sizeof(RANGE_TYPE_STRINGS))
@@ -218,20 +151,20 @@ qint64 QmlProfilerData::traceEndTime() const
return d->traceEndTime;
}
-void QmlProfilerData::addQmlEvent(QQmlProfilerDefinitions::RangeType type,
- QQmlProfilerDefinitions::BindingType bindingType,
- qint64 startTime,
- qint64 duration,
- const QStringList &data,
- const QQmlEventLocation &location)
+void QmlProfilerData::addEvent(const QQmlProfilerEvent &event)
{
setState(AcquiringData);
+ d->events.append(event);
+}
+
+void QmlProfilerData::addEventType(const QQmlProfilerEventType &type)
+{
+ QQmlProfilerEventType newType = type;
QString details;
// generate details string
- if (!data.isEmpty()) {
- details = data.join(QLatin1Char(' ')).replace(
- QLatin1Char('\n'), QLatin1Char(' ')).simplified();
+ if (!type.data().isEmpty()) {
+ details = type.data().simplified();
QRegularExpression rewrite(QStringLiteral("^\\(function \\$(\\w+)\\(\\) \\{ (return |)(.+) \\}\\)$"));
QRegularExpressionMatch match = rewrite.match(details);
if (match.hasMatch()) {
@@ -241,223 +174,132 @@ void QmlProfilerData::addQmlEvent(QQmlProfilerDefinitions::RangeType type,
details = details.mid(details.lastIndexOf(QLatin1Char('/')) + 1);
}
- QQmlEventLocation eventLocation = location;
- QString displayName, eventHashStr;
- // generate hash
- if (eventLocation.filename.isEmpty()) {
- displayName = tr("<bytecode>");
- eventHashStr = getHashStringForQmlEvent(eventLocation, type);
- } else {
- const QString filePath = QUrl(eventLocation.filename).path();
- displayName = filePath.midRef(
- filePath.lastIndexOf(QLatin1Char('/')) + 1) +
- QLatin1Char(':') + QString::number(eventLocation.line);
- eventHashStr = getHashStringForQmlEvent(eventLocation, type);
- }
-
- QmlRangeEventData *newEvent;
- if (d->eventDescriptions.contains(eventHashStr)) {
- newEvent = d->eventDescriptions[eventHashStr];
- } else {
- newEvent = new QmlRangeEventData(displayName, bindingType, eventHashStr, location, details,
- QQmlProfilerDefinitions::MaximumMessage, type);
- d->eventDescriptions.insert(eventHashStr, newEvent);
- }
-
- QmlRangeEventStartInstance rangeEventStartInstance(startTime, duration, -1, -1, -1, newEvent);
-
- d->startInstanceList.append(rangeEventStartInstance);
-}
-
-void QmlProfilerData::addFrameEvent(qint64 time, int framerate, int animationcount, int threadId)
-{
- setState(AcquiringData);
-
- QString details = tr("Animation Timer Update");
- QString displayName = tr("<Animation Update>");
- QString eventHashStr = displayName;
-
- QmlRangeEventData *newEvent;
- if (d->eventDescriptions.contains(eventHashStr)) {
- newEvent = d->eventDescriptions[eventHashStr];
- } else {
- newEvent = new QmlRangeEventData(displayName, QQmlProfilerDefinitions::AnimationFrame,
- eventHashStr,
- QQmlEventLocation(), details,
- QQmlProfilerDefinitions::Event,
- QQmlProfilerDefinitions::MaximumRangeType);
- d->eventDescriptions.insert(eventHashStr, newEvent);
- }
-
- QmlRangeEventStartInstance rangeEventStartInstance(time, -1, framerate, animationcount,
- threadId, newEvent);
-
- d->startInstanceList.append(rangeEventStartInstance);
-}
-
-void QmlProfilerData::addSceneGraphFrameEvent(QQmlProfilerDefinitions::SceneGraphFrameType type,
- qint64 time, qint64 numericData1, qint64 numericData2,
- qint64 numericData3, qint64 numericData4,
- qint64 numericData5)
-{
- setState(AcquiringData);
-
- QString eventHashStr = QString::fromLatin1("SceneGraph:%1").arg(type);
- QmlRangeEventData *newEvent;
- if (d->eventDescriptions.contains(eventHashStr)) {
- newEvent = d->eventDescriptions[eventHashStr];
- } else {
- newEvent = new QmlRangeEventData(QStringLiteral("<SceneGraph>"), type, eventHashStr,
- QQmlEventLocation(), QString(),
- QQmlProfilerDefinitions::SceneGraphFrame,
- QQmlProfilerDefinitions::MaximumRangeType);
- d->eventDescriptions.insert(eventHashStr, newEvent);
- }
+ newType.setData(details);
- QmlRangeEventStartInstance rangeEventStartInstance(time, numericData1, numericData2,
- numericData3, numericData4, numericData5,
- newEvent);
- d->startInstanceList.append(rangeEventStartInstance);
-}
-
-void QmlProfilerData::addPixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventType type,
- qint64 time, const QString &location,
- int numericData1, int numericData2)
-{
- setState(AcquiringData);
-
- QString filePath = QUrl(location).path();
-
- const QString eventHashStr = filePath.midRef(filePath.lastIndexOf(QLatin1Char('/')) + 1)
- + QLatin1Char(':') + QString::number(type);
- QmlRangeEventData *newEvent;
- if (d->eventDescriptions.contains(eventHashStr)) {
- newEvent = d->eventDescriptions[eventHashStr];
- } else {
- newEvent = new QmlRangeEventData(eventHashStr, type, eventHashStr,
- QQmlEventLocation(location, -1, -1), QString(),
- QQmlProfilerDefinitions::PixmapCacheEvent,
- QQmlProfilerDefinitions::MaximumRangeType);
- d->eventDescriptions.insert(eventHashStr, newEvent);
+ QString displayName;
+ switch (type.message()) {
+ case QQmlProfilerDefinitions::Event: {
+ switch (type.detailType()) {
+ case QQmlProfilerDefinitions::Mouse:
+ case QQmlProfilerDefinitions::Key:
+ displayName = QString::fromLatin1("Input:%1").arg(type.detailType());
+ break;
+ case QQmlProfilerDefinitions::AnimationFrame:
+ displayName = QString::fromLatin1("AnimationFrame");
+ break;
+ default:
+ displayName = QString::fromLatin1("Unknown");
+ }
+ break;
}
-
- QmlRangeEventStartInstance rangeEventStartInstance(time, numericData1, numericData2, 0, 0, 0,
- newEvent);
- d->startInstanceList.append(rangeEventStartInstance);
-}
-
-void QmlProfilerData::addMemoryEvent(QQmlProfilerDefinitions::MemoryType type, qint64 time,
- qint64 size)
-{
- setState(AcquiringData);
- QString eventHashStr = QString::fromLatin1("MemoryAllocation:%1").arg(type);
- QmlRangeEventData *newEvent;
- if (d->eventDescriptions.contains(eventHashStr)) {
- newEvent = d->eventDescriptions[eventHashStr];
- } else {
- newEvent = new QmlRangeEventData(eventHashStr, type, eventHashStr, QQmlEventLocation(),
- QString(), QQmlProfilerDefinitions::MemoryAllocation,
- QQmlProfilerDefinitions::MaximumRangeType);
- d->eventDescriptions.insert(eventHashStr, newEvent);
+ case QQmlProfilerDefinitions::RangeStart:
+ case QQmlProfilerDefinitions::RangeData:
+ case QQmlProfilerDefinitions::RangeLocation:
+ case QQmlProfilerDefinitions::RangeEnd:
+ case QQmlProfilerDefinitions::Complete:
+ Q_UNREACHABLE();
+ break;
+ case QQmlProfilerDefinitions::PixmapCacheEvent: {
+ const QString filePath = QUrl(type.location().filename()).path();
+ displayName = filePath.midRef(filePath.lastIndexOf(QLatin1Char('/')) + 1)
+ + QLatin1Char(':') + QString::number(type.detailType());
+ break;
}
- QmlRangeEventStartInstance rangeEventStartInstance(time, size, 0, 0, 0, 0, newEvent);
- d->startInstanceList.append(rangeEventStartInstance);
-}
-
-void QmlProfilerData::addInputEvent(QQmlProfilerDefinitions::InputEventType type, qint64 time,
- int a, int b)
-{
- setState(AcquiringData);
-
- QQmlProfilerDefinitions::EventType eventType;
- switch (type) {
- case QQmlProfilerDefinitions::InputKeyPress:
- case QQmlProfilerDefinitions::InputKeyRelease:
- case QQmlProfilerDefinitions::InputKeyUnknown:
- eventType = QQmlProfilerDefinitions::Key;
+ case QQmlProfilerDefinitions::SceneGraphFrame:
+ displayName = QString::fromLatin1("SceneGraph:%1").arg(type.detailType());
break;
- default:
- eventType = QQmlProfilerDefinitions::Mouse;
+ case QQmlProfilerDefinitions::MemoryAllocation:
+ displayName = QString::fromLatin1("MemoryAllocation:%1").arg(type.detailType());
+ break;
+ case QQmlProfilerDefinitions::DebugMessage:
+ displayName = QString::fromLatin1("DebugMessage:%1").arg(type.detailType());
+ break;
+ case QQmlProfilerDefinitions::MaximumMessage: {
+ const QQmlProfilerEventLocation eventLocation = type.location();
+ // generate hash
+ if (eventLocation.filename().isEmpty()) {
+ displayName = QString::fromLatin1("Unknown");
+ } else {
+ const QString filePath = QUrl(eventLocation.filename()).path();
+ displayName = filePath.midRef(
+ filePath.lastIndexOf(QLatin1Char('/')) + 1) +
+ QLatin1Char(':') + QString::number(eventLocation.line());
+ }
break;
}
-
- QString eventHashStr = QString::fromLatin1("Input:%1").arg(eventType);
-
- QmlRangeEventData *newEvent;
- if (d->eventDescriptions.contains(eventHashStr)) {
- newEvent = d->eventDescriptions[eventHashStr];
- } else {
- newEvent = new QmlRangeEventData(QString(), eventType, eventHashStr, QQmlEventLocation(),
- QString(), QQmlProfilerDefinitions::Event,
- QQmlProfilerDefinitions::MaximumRangeType);
- d->eventDescriptions.insert(eventHashStr, newEvent);
}
- d->startInstanceList.append(QmlRangeEventStartInstance(time, -1, type, a, b, newEvent));
+ newType.setDisplayName(displayName);
+ d->eventTypes.append(newType);
}
void QmlProfilerData::computeQmlTime()
{
// compute levels
- QHash<int, qint64> endtimesPerLevel;
- int minimumLevel = 1;
- int level = minimumLevel;
-
- for (int i = 0; i < d->startInstanceList.count(); i++) {
- qint64 st = d->startInstanceList.at(i).startTime;
+ qint64 level0Start = -1;
+ int level = 0;
- if (d->startInstanceList.at(i).data->rangeType == QQmlProfilerDefinitions::Painting) {
+ for (const QQmlProfilerEvent &event : qAsConst(d->events)) {
+ const QQmlProfilerEventType &type = d->eventTypes.at(event.typeIndex());
+ if (type.message() != QQmlProfilerDefinitions::MaximumMessage)
continue;
- }
-
- // general level
- if (endtimesPerLevel.value(level) > st) {
- level++;
- } else {
- while (level > minimumLevel && endtimesPerLevel[level-1] <= st)
- level--;
- }
- endtimesPerLevel[level] = st + d->startInstanceList.at(i).duration;
- if (level == minimumLevel) {
- d->qmlMeasuredTime += d->startInstanceList.at(i).duration;
+ switch (type.rangeType()) {
+ case QQmlProfilerDefinitions::Compiling:
+ case QQmlProfilerDefinitions::Creating:
+ case QQmlProfilerDefinitions::Binding:
+ case QQmlProfilerDefinitions::HandlingSignal:
+ case QQmlProfilerDefinitions::Javascript:
+ switch (event.rangeStage()) {
+ case QQmlProfilerDefinitions::RangeStart:
+ if (level++ == 0)
+ level0Start = event.timestamp();
+ break;
+ case QQmlProfilerDefinitions::RangeEnd:
+ if (--level == 0)
+ d->qmlMeasuredTime += event.timestamp() - level0Start;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
}
}
}
-bool compareStartTimes(const QmlRangeEventStartInstance &t1, const QmlRangeEventStartInstance &t2)
+bool compareStartTimes(const QQmlProfilerEvent &t1, const QQmlProfilerEvent &t2)
{
- return t1.startTime < t2.startTime;
+ return t1.timestamp() < t2.timestamp();
}
void QmlProfilerData::sortStartTimes()
{
- if (d->startInstanceList.count() < 2)
+ if (d->events.count() < 2)
return;
// assuming startTimes is partially sorted
// identify blocks of events and sort them with quicksort
- QVector<QmlRangeEventStartInstance>::iterator itFrom = d->startInstanceList.end() - 2;
- QVector<QmlRangeEventStartInstance>::iterator itTo = d->startInstanceList.end() - 1;
+ QVector<QQmlProfilerEvent>::iterator itFrom = d->events.end() - 2;
+ QVector<QQmlProfilerEvent>::iterator itTo = d->events.end() - 1;
- while (itFrom != d->startInstanceList.begin() && itTo != d->startInstanceList.begin()) {
+ while (itFrom != d->events.begin() && itTo != d->events.begin()) {
// find block to sort
- while ( itFrom != d->startInstanceList.begin()
- && itTo->startTime > itFrom->startTime ) {
+ while (itFrom != d->events.begin() && itTo->timestamp() > itFrom->timestamp()) {
--itTo;
itFrom = itTo - 1;
}
// if we're at the end of the list
- if (itFrom == d->startInstanceList.begin())
+ if (itFrom == d->events.begin())
break;
// find block length
- while ( itFrom != d->startInstanceList.begin()
- && itTo->startTime <= itFrom->startTime )
+ while (itFrom != d->events.begin() && itTo->timestamp() <= itFrom->timestamp())
--itFrom;
- if (itTo->startTime <= itFrom->startTime)
+ if (itTo->timestamp() <= itFrom->timestamp())
std::sort(itFrom, itTo + 1, compareStartTimes);
else
std::sort(itFrom + 1, itTo + 1, compareStartTimes);
@@ -479,9 +321,88 @@ void QmlProfilerData::complete()
bool QmlProfilerData::isEmpty() const
{
- return d->startInstanceList.isEmpty();
+ return d->events.isEmpty();
}
+struct StreamWriter {
+ QString error;
+
+ StreamWriter(const QString &filename)
+ {
+ if (!filename.isEmpty()) {
+ file.setFileName(filename);
+ if (!file.open(QIODevice::WriteOnly)) {
+ error = QmlProfilerData::tr("Could not open %1 for writing").arg(filename);
+ return;
+ }
+ } else {
+ if (!file.open(stdout, QIODevice::WriteOnly)) {
+ error = QmlProfilerData::tr("Could not open stdout for writing");
+ return;
+ }
+ }
+
+ stream.setDevice(&file);
+ stream.setAutoFormatting(true);
+ stream.writeStartDocument();
+ writeStartElement("trace");
+ }
+
+ ~StreamWriter() {
+ writeEndElement();
+ stream.writeEndDocument();
+ file.close();
+ }
+
+ template<typename Number>
+ void writeAttribute(const char *name, Number number)
+ {
+ stream.writeAttribute(QLatin1String(name), QString::number(number));
+ }
+
+ void writeAttribute(const char *name, const char *value)
+ {
+ stream.writeAttribute(QLatin1String(name), QLatin1String(value));
+ }
+
+ void writeAttribute(const char *name, const QQmlProfilerEvent &event, int i, bool printZero = true)
+ {
+ const qint64 number = event.number<qint64>(i);
+ if (printZero || number != 0)
+ writeAttribute(name, number);
+ }
+
+ template<typename Number>
+ void writeTextElement(const char *name, Number number)
+ {
+ writeTextElement(name, QString::number(number));
+ }
+
+ void writeTextElement(const char *name, const char *value)
+ {
+ stream.writeTextElement(QLatin1String(name), QLatin1String(value));
+ }
+
+ void writeTextElement(const char *name, const QString &value)
+ {
+ stream.writeTextElement(QLatin1String(name), value);
+ }
+
+ void writeStartElement(const char *name)
+ {
+ stream.writeStartElement(QLatin1String(name));
+ }
+
+ void writeEndElement()
+ {
+ stream.writeEndElement();
+ }
+
+private:
+ QFile file;
+ QXmlStreamWriter stream;
+};
+
bool QmlProfilerData::save(const QString &filename)
{
if (isEmpty()) {
@@ -489,157 +410,178 @@ bool QmlProfilerData::save(const QString &filename)
return false;
}
- QFile file;
- if (!filename.isEmpty()) {
- file.setFileName(filename);
- if (!file.open(QIODevice::WriteOnly)) {
- emit error(tr("Could not open %1 for writing").arg(filename));
- return false;
- }
- } else {
- if (!file.open(stdout, QIODevice::WriteOnly)) {
- emit error(tr("Could not open stdout for writing"));
- return false;
- }
+ StreamWriter stream(filename);
+ if (!stream.error.isEmpty()) {
+ emit error(stream.error);
+ return false;
}
- QXmlStreamWriter stream(&file);
- stream.setAutoFormatting(true);
- stream.writeStartDocument();
-
- stream.writeStartElement(QStringLiteral("trace"));
- stream.writeAttribute(QStringLiteral("version"), PROFILER_FILE_VERSION);
-
- stream.writeAttribute(QStringLiteral("traceStart"), QString::number(traceStartTime()));
- stream.writeAttribute(QStringLiteral("traceEnd"), QString::number(traceEndTime()));
-
- stream.writeStartElement(QStringLiteral("eventData"));
- stream.writeAttribute(QStringLiteral("totalTime"), QString::number(d->qmlMeasuredTime));
-
- const auto eventDescriptionsKeys = d->eventDescriptions.keys();
- for (auto it = d->eventDescriptions.cbegin(), end = d->eventDescriptions.cend();
- it != end; ++it) {
- const QmlRangeEventData *eventData = it.value();
- stream.writeStartElement(QStringLiteral("event"));
- stream.writeAttribute(QStringLiteral("index"), QString::number(
- eventDescriptionsKeys.indexOf(eventData->eventHashStr)));
- if (!eventData->displayName.isEmpty())
- stream.writeTextElement(QStringLiteral("displayname"), eventData->displayName);
- if (eventData->rangeType != QQmlProfilerDefinitions::MaximumRangeType)
- stream.writeTextElement(QStringLiteral("type"),
- qmlRangeTypeAsString(eventData->rangeType));
- else
- stream.writeTextElement(QStringLiteral("type"),
- qmlMessageAsString(eventData->message));
- if (!eventData->location.filename.isEmpty())
- stream.writeTextElement(QStringLiteral("filename"), eventData->location.filename);
- if (eventData->location.line >= 0)
- stream.writeTextElement(QStringLiteral("line"),
- QString::number(eventData->location.line));
- if (eventData->location.column >= 0)
- stream.writeTextElement(QStringLiteral("column"),
- QString::number(eventData->location.column));
- if (!eventData->details.isEmpty())
- stream.writeTextElement(QStringLiteral("details"), eventData->details);
- if (eventData->rangeType == QQmlProfilerDefinitions::Binding)
- stream.writeTextElement(QStringLiteral("bindingType"),
- QString::number((int)eventData->detailType));
- else if (eventData->message == QQmlProfilerDefinitions::Event) {
- switch (eventData->detailType) {
+ stream.writeAttribute("version", PROFILER_FILE_VERSION);
+ stream.writeAttribute("traceStart", traceStartTime());
+ stream.writeAttribute("traceEnd", traceEndTime());
+
+ stream.writeStartElement("eventData");
+ stream.writeAttribute("totalTime", d->qmlMeasuredTime);
+
+ for (int typeIndex = 0, end = d->eventTypes.size(); typeIndex < end; ++typeIndex) {
+ const QQmlProfilerEventType &eventData = d->eventTypes.at(typeIndex);
+ stream.writeStartElement("event");
+ stream.writeAttribute("index", typeIndex);
+ if (!eventData.displayName().isEmpty())
+ stream.writeTextElement("displayname", eventData.displayName());
+
+ stream.writeTextElement("type",
+ eventData.rangeType() == QQmlProfilerDefinitions::MaximumRangeType
+ ? qmlMessageAsString(eventData.message())
+ : qmlRangeTypeAsString(eventData.rangeType()));
+
+ const QQmlProfilerEventLocation location = eventData.location();
+ if (!location.filename().isEmpty())
+ stream.writeTextElement("filename", location.filename());
+ if (location.line() >= 0)
+ stream.writeTextElement("line", location.line());
+ if (location.column() >= 0)
+ stream.writeTextElement("column", location.column());
+ if (!eventData.data().isEmpty())
+ stream.writeTextElement("details", eventData.data());
+ if (eventData.rangeType() == QQmlProfilerDefinitions::Binding)
+ stream.writeTextElement("bindingType", eventData.detailType());
+ else if (eventData.message() == QQmlProfilerDefinitions::Event) {
+ switch (eventData.detailType()) {
case QQmlProfilerDefinitions::AnimationFrame:
- stream.writeTextElement(QStringLiteral("animationFrame"),
- QString::number((int)eventData->detailType));
+ stream.writeTextElement("animationFrame", eventData.detailType());
break;
case QQmlProfilerDefinitions::Key:
- stream.writeTextElement(QStringLiteral("keyEvent"),
- QString::number((int)eventData->detailType));
+ stream.writeTextElement("keyEvent", eventData.detailType());
break;
case QQmlProfilerDefinitions::Mouse:
- stream.writeTextElement(QStringLiteral("mouseEvent"),
- QString::number((int)eventData->detailType));
+ stream.writeTextElement("mouseEvent", eventData.detailType());
break;
}
- } else if (eventData->message == QQmlProfilerDefinitions::PixmapCacheEvent)
- stream.writeTextElement(QStringLiteral("cacheEventType"),
- QString::number((int)eventData->detailType));
- else if (eventData->message == QQmlProfilerDefinitions::SceneGraphFrame)
- stream.writeTextElement(QStringLiteral("sgEventType"),
- QString::number((int)eventData->detailType));
- else if (eventData->message == QQmlProfilerDefinitions::MemoryAllocation)
- stream.writeTextElement(QStringLiteral("memoryEventType"),
- QString::number((int)eventData->detailType));
+ } else if (eventData.message() == QQmlProfilerDefinitions::PixmapCacheEvent)
+ stream.writeTextElement("cacheEventType", eventData.detailType());
+ else if (eventData.message() == QQmlProfilerDefinitions::SceneGraphFrame)
+ stream.writeTextElement("sgEventType", eventData.detailType());
+ else if (eventData.message() == QQmlProfilerDefinitions::MemoryAllocation)
+ stream.writeTextElement("memoryEventType", eventData.detailType());
stream.writeEndElement();
}
stream.writeEndElement(); // eventData
- stream.writeStartElement(QStringLiteral("profilerDataModel"));
- for (const QmlRangeEventStartInstance &event : qAsConst(d->startInstanceList)) {
- stream.writeStartElement(QStringLiteral("range"));
- stream.writeAttribute(QStringLiteral("startTime"), QString::number(event.startTime));
- if (event.duration >= 0)
- stream.writeAttribute(QStringLiteral("duration"),
- QString::number(event.duration));
- stream.writeAttribute(QStringLiteral("eventIndex"), QString::number(
- eventDescriptionsKeys.indexOf(event.data->eventHashStr)));
- if (event.data->message == QQmlProfilerDefinitions::Event) {
- if (event.data->detailType == QQmlProfilerDefinitions::AnimationFrame) {
+ stream.writeStartElement("profilerDataModel");
+
+ auto sendEvent = [&](const QQmlProfilerEvent &event, qint64 duration = 0) {
+ const QQmlProfilerEventType &type = d->eventTypes.at(event.typeIndex());
+ stream.writeStartElement("range");
+ stream.writeAttribute("startTime", event.timestamp());
+ if (duration != 0)
+ stream.writeAttribute("duration", duration);
+ stream.writeAttribute("eventIndex", event.typeIndex());
+ if (type.message() == QQmlProfilerDefinitions::Event) {
+ if (type.detailType() == QQmlProfilerDefinitions::AnimationFrame) {
// special: animation frame
- stream.writeAttribute(QStringLiteral("framerate"), QString::number(event.frameRate));
- stream.writeAttribute(QStringLiteral("animationcount"),
- QString::number(event.animationCount));
- stream.writeAttribute(QStringLiteral("thread"), QString::number(event.threadId));
- } else if (event.data->detailType == QQmlProfilerDefinitions::Key ||
- event.data->detailType == QQmlProfilerDefinitions::Mouse) {
+ stream.writeAttribute("framerate", event, 0);
+ stream.writeAttribute("animationcount", event, 1);
+ stream.writeAttribute("thread", event, 2);
+ } else if (type.detailType() == QQmlProfilerDefinitions::Key ||
+ type.detailType() == QQmlProfilerDefinitions::Mouse) {
// numerical value here, to keep the format a bit more compact
- stream.writeAttribute(QStringLiteral("type"),
- QString::number(event.inputType));
- stream.writeAttribute(QStringLiteral("data1"),
- QString::number(event.inputA));
- stream.writeAttribute(QStringLiteral("data2"),
- QString::number(event.inputB));
+ stream.writeAttribute("type", event, 0);
+ stream.writeAttribute("data1", event, 1);
+ stream.writeAttribute("data2", event, 2);
}
- } else if (event.data->message == QQmlProfilerDefinitions::PixmapCacheEvent) {
+ } else if (type.message() == QQmlProfilerDefinitions::PixmapCacheEvent) {
// special: pixmap cache event
- if (event.data->detailType == QQmlProfilerDefinitions::PixmapSizeKnown) {
- stream.writeAttribute(QStringLiteral("width"),
- QString::number(event.numericData1));
- stream.writeAttribute(QStringLiteral("height"),
- QString::number(event.numericData2));
- } else if (event.data->detailType ==
- QQmlProfilerDefinitions::PixmapReferenceCountChanged ||
- event.data->detailType ==
- QQmlProfilerDefinitions::PixmapCacheCountChanged) {
- stream.writeAttribute(QStringLiteral("refCount"),
- QString::number(event.numericData1));
+ if (type.detailType() == QQmlProfilerDefinitions::PixmapSizeKnown) {
+ stream.writeAttribute("width", event, 0);
+ stream.writeAttribute("height", event, 1);
+ } else if (type.detailType() == QQmlProfilerDefinitions::PixmapReferenceCountChanged
+ || type.detailType() == QQmlProfilerDefinitions::PixmapCacheCountChanged) {
+ stream.writeAttribute("refCount", event, 1);
}
- } else if (event.data->message == QQmlProfilerDefinitions::SceneGraphFrame) {
- // special: scenegraph frame events
- if (event.numericData1 > 0)
- stream.writeAttribute(QStringLiteral("timing1"),
- QString::number(event.numericData1));
- if (event.numericData2 > 0)
- stream.writeAttribute(QStringLiteral("timing2"),
- QString::number(event.numericData2));
- if (event.numericData3 > 0)
- stream.writeAttribute(QStringLiteral("timing3"),
- QString::number(event.numericData3));
- if (event.numericData4 > 0)
- stream.writeAttribute(QStringLiteral("timing4"),
- QString::number(event.numericData4));
- if (event.numericData5 > 0)
- stream.writeAttribute(QStringLiteral("timing5"),
- QString::number(event.numericData5));
- } else if (event.data->message == QQmlProfilerDefinitions::MemoryAllocation) {
- stream.writeAttribute(QStringLiteral("amount"), QString::number(event.numericData1));
+ } else if (type.message() == QQmlProfilerDefinitions::SceneGraphFrame) {
+ stream.writeAttribute("timing1", event, 0, false);
+ stream.writeAttribute("timing2", event, 1, false);
+ stream.writeAttribute("timing3", event, 2, false);
+ stream.writeAttribute("timing4", event, 3, false);
+ stream.writeAttribute("timing5", event, 4, false);
+ } else if (type.message() == QQmlProfilerDefinitions::MemoryAllocation) {
+ stream.writeAttribute("amount", event, 0);
}
stream.writeEndElement();
+ };
+
+ QQueue<QQmlProfilerEvent> pointEvents;
+ QQueue<QQmlProfilerEvent> rangeStarts[QQmlProfilerDefinitions::MaximumRangeType];
+ QStack<qint64> rangeEnds[QQmlProfilerDefinitions::MaximumRangeType];
+ int level = 0;
+
+ auto sendPending = [&]() {
+ forever {
+ int minimum = QQmlProfilerDefinitions::MaximumRangeType;
+ qint64 minimumTime = std::numeric_limits<qint64>::max();
+ for (int i = 0; i < QQmlProfilerDefinitions::MaximumRangeType; ++i) {
+ const QQueue<QQmlProfilerEvent> &starts = rangeStarts[i];
+ if (starts.isEmpty())
+ continue;
+ if (starts.head().timestamp() < minimumTime) {
+ minimumTime = starts.head().timestamp();
+ minimum = i;
+ }
+ }
+ if (minimum == QQmlProfilerDefinitions::MaximumRangeType)
+ break;
+
+ while (!pointEvents.isEmpty() && pointEvents.front().timestamp() < minimumTime)
+ sendEvent(pointEvents.dequeue());
+
+ sendEvent(rangeStarts[minimum].dequeue(),
+ rangeEnds[minimum].pop() - minimumTime);
+ }
+ };
+
+ for (const QQmlProfilerEvent &event : qAsConst(d->events)) {
+ const QQmlProfilerEventType &type = d->eventTypes.at(event.typeIndex());
+
+ if (type.rangeType() != QQmlProfilerDefinitions::MaximumRangeType) {
+ QQueue<QQmlProfilerEvent> &starts = rangeStarts[type.rangeType()];
+ switch (event.rangeStage()) {
+ case QQmlProfilerDefinitions::RangeStart: {
+ ++level;
+ starts.enqueue(event);
+ break;
+ }
+ case QQmlProfilerDefinitions::RangeEnd: {
+ QStack<qint64> &ends = rangeEnds[type.rangeType()];
+ if (starts.length() > ends.length()) {
+ ends.push(event.timestamp());
+ if (--level == 0)
+ sendPending();
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ } else {
+ if (level == 0)
+ sendEvent(event);
+ else
+ pointEvents.enqueue(event);
+ }
}
- stream.writeEndElement(); // profilerDataModel
- stream.writeEndElement(); // trace
- stream.writeEndDocument();
+ for (int i = 0; i < QQmlProfilerDefinitions::MaximumRangeType; ++i) {
+ while (rangeEnds[i].length() < rangeStarts[i].length()) {
+ rangeEnds[i].push(d->traceEndTime);
+ --level;
+ }
+ }
+
+ sendPending();
+
+ stream.writeEndElement(); // profilerDataModel
- file.close();
return true;
}
@@ -683,4 +625,9 @@ void QmlProfilerData::setState(QmlProfilerData::State state)
return;
}
+int QmlProfilerData::numLoadedEventTypes() const
+{
+ return d->eventTypes.length();
+}
+
#include "moc_qmlprofilerdata.cpp"
diff --git a/tools/qmlprofiler/qmlprofilerdata.h b/tools/qmlprofiler/qmlprofilerdata.h
index 00ef037071..2be0b73aee 100644
--- a/tools/qmlprofiler/qmlprofilerdata.h
+++ b/tools/qmlprofiler/qmlprofilerdata.h
@@ -29,13 +29,14 @@
#ifndef QMLPROFILERDATA_H
#define QMLPROFILERDATA_H
-#include <private/qqmleventlocation_p.h>
#include <private/qqmlprofilerdefinitions_p.h>
+#include <private/qqmlprofilereventlocation_p.h>
+#include <private/qqmlprofilereventreceiver_p.h>
#include <QObject>
class QmlProfilerDataPrivate;
-class QmlProfilerData : public QObject
+class QmlProfilerData : public QQmlProfilerEventReceiver
{
Q_OBJECT
public:
@@ -49,7 +50,11 @@ public:
explicit QmlProfilerData(QObject *parent = 0);
~QmlProfilerData();
- static QString getHashStringForQmlEvent(const QQmlEventLocation &location, int eventType);
+ int numLoadedEventTypes() const override;
+ void addEventType(const QQmlProfilerEventType &type) override;
+ void addEvent(const QQmlProfilerEvent &event) override;
+
+ static QString getHashStringForQmlEvent(const QQmlProfilerEventLocation &location, int eventType);
static QString qmlRangeTypeAsString(QQmlProfilerDefinitions::RangeType type);
static QString qmlMessageAsString(QQmlProfilerDefinitions::Message type);
@@ -61,18 +66,6 @@ public:
void clear();
void setTraceEndTime(qint64 time);
void setTraceStartTime(qint64 time);
- void addQmlEvent(QQmlProfilerDefinitions::RangeType type,
- QQmlProfilerDefinitions::BindingType bindingType,
- qint64 startTime, qint64 duration, const QStringList &data,
- const QQmlEventLocation &location);
- void addFrameEvent(qint64 time, int framerate, int animationcount, int threadId);
- void addSceneGraphFrameEvent(QQmlProfilerDefinitions::SceneGraphFrameType type, qint64 time,
- qint64 numericData1, qint64 numericData2, qint64 numericData3,
- qint64 numericData4, qint64 numericData5);
- void addPixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventType type, qint64 time,
- const QString &location, int numericData1, int numericData2);
- void addMemoryEvent(QQmlProfilerDefinitions::MemoryType type, qint64 time, qint64 size);
- void addInputEvent(QQmlProfilerDefinitions::InputEventType type, qint64 time, int a, int b);
void complete();
bool save(const QString &filename);