summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/plugins/qmlprofiler/flamegraphmodel.cpp46
-rw-r--r--src/plugins/qmlprofiler/flamegraphmodel.h2
-rw-r--r--src/plugins/qmlprofiler/flamegraphview.cpp20
-rw-r--r--src/plugins/qmlprofiler/flamegraphview.h5
-rw-r--r--src/plugins/qmlprofiler/memoryusagemodel.cpp8
-rw-r--r--src/plugins/qmlprofiler/memoryusagemodel.h7
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp12
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp198
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerdatamodel.h11
-rw-r--r--src/plugins/qmlprofiler/qmlprofilereventsview.h5
-rw-r--r--src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp88
-rw-r--r--src/plugins/qmlprofiler/qmlprofilermodelmanager.h14
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerrangemodel.cpp11
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerrangemodel.h2
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp226
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.h9
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp27
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerstatisticsview.h3
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertimelinemodel.cpp18
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertimelinemodel.h2
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertraceclient.cpp250
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertraceclient.h8
-rw-r--r--src/plugins/qmlprofiler/qmlprofilertracefile.cpp107
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerviewmanager.cpp9
24 files changed, 462 insertions, 626 deletions
diff --git a/src/plugins/qmlprofiler/flamegraphmodel.cpp b/src/plugins/qmlprofiler/flamegraphmodel.cpp
index 2a2055a0df..f5664dc5df 100644
--- a/src/plugins/qmlprofiler/flamegraphmodel.cpp
+++ b/src/plugins/qmlprofiler/flamegraphmodel.cpp
@@ -63,7 +63,7 @@ FlameGraphModel::FlameGraphModel(QmlProfilerModelManager *modelManager,
void FlameGraphModel::clear()
{
beginResetModel();
- m_stackBottom = FlameGraphData();
+ m_stackBottom = FlameGraphData(0, -1, 1);
m_callStack.clear();
m_callStack.append(QmlEvent());
m_stackTop = &m_stackBottom;
@@ -102,15 +102,16 @@ void FlameGraphModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
beginResetModel();
const QmlEvent *potentialParent = &(m_callStack.top());
- while (potentialParent->isValid() &&
- potentialParent->timestamp() + potentialParent->duration() <= event.timestamp()) {
+ if (event.rangeStage() == RangeEnd) {
+ m_stackTop->duration += event.timestamp() - potentialParent->timestamp();
m_callStack.pop();
m_stackTop = m_stackTop->parent;
potentialParent = &(m_callStack.top());
+ } else {
+ QTC_ASSERT(event.rangeStage() == RangeStart, return);
+ m_callStack.push(event);
+ m_stackTop = pushChild(m_stackTop, event);
}
-
- m_callStack.push(event);
- m_stackTop = pushChild(m_stackTop, event);
}
void FlameGraphModel::finalize()
@@ -126,31 +127,6 @@ void FlameGraphModel::onModelManagerStateChanged()
{
if (m_modelManager->state() == QmlProfilerModelManager::ClearingData)
clear();
- else if (m_modelManager->state() == QmlProfilerModelManager::ProcessingData)
- loadData();
-}
-
-void FlameGraphModel::loadData(qint64 rangeStart, qint64 rangeEnd)
-{
- clear();
- const bool checkRanges = (rangeStart != -1) && (rangeEnd != -1);
-
- const QVector<QmlEvent> &eventList = m_modelManager->qmlModel()->events();
- const QVector<QmlEventType> &typesList = m_modelManager->qmlModel()->eventTypes();
-
- for (int i = 0; i < eventList.size(); ++i) {
- const QmlEvent &event = eventList[i];
-
- if (checkRanges) {
- if ((event.timestamp() + event.duration() < rangeStart)
- || (event.timestamp() > rangeEnd))
- continue;
- }
-
- loadEvent(event, typesList[event.typeIndex()]);
- }
-
- finalize();
}
static QString nameForType(RangeType typeNumber)
@@ -223,12 +199,11 @@ FlameGraphData *FlameGraphModel::pushChild(FlameGraphData *parent, const QmlEven
foreach (FlameGraphData *child, parent->children) {
if (child->typeIndex == data.typeIndex()) {
++child->calls;
- child->duration += data.duration();
return child;
}
}
- FlameGraphData *child = new FlameGraphData(parent, data.typeIndex(), data.duration());
+ FlameGraphData *child = new FlameGraphData(parent, data.typeIndex());
parent->children.append(child);
return child;
}
@@ -293,5 +268,10 @@ QHash<int, QByteArray> FlameGraphModel::roleNames() const
return names;
}
+QmlProfilerModelManager *FlameGraphModel::modelManager() const
+{
+ return m_modelManager;
+}
+
} // namespace Internal
} // namespace QmlProfiler
diff --git a/src/plugins/qmlprofiler/flamegraphmodel.h b/src/plugins/qmlprofiler/flamegraphmodel.h
index 547d3bc890..0b42aa3946 100644
--- a/src/plugins/qmlprofiler/flamegraphmodel.h
+++ b/src/plugins/qmlprofiler/flamegraphmodel.h
@@ -80,12 +80,12 @@ public:
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
+ QmlProfilerModelManager *modelManager() const;
public slots:
void loadEvent(const QmlEvent &event, const QmlEventType &type);
void finalize();
void onModelManagerStateChanged();
- void loadData(qint64 rangeStart = -1, qint64 rangeEnd = -1);
void loadNotes(int typeId, bool emitSignal);
void clear();
diff --git a/src/plugins/qmlprofiler/flamegraphview.cpp b/src/plugins/qmlprofiler/flamegraphview.cpp
index cf5846a258..f461b4332d 100644
--- a/src/plugins/qmlprofiler/flamegraphview.cpp
+++ b/src/plugins/qmlprofiler/flamegraphview.cpp
@@ -37,7 +37,7 @@ namespace Internal {
FlameGraphView::FlameGraphView(QWidget *parent, QmlProfilerModelManager *manager) :
QmlProfilerEventsView(parent), m_content(new QQuickWidget(this)),
- m_model(new FlameGraphModel(manager, this)), m_isRestrictedToRange(false)
+ m_model(new FlameGraphModel(manager, this))
{
setWindowTitle(QStringLiteral("Flamegraph"));
setObjectName(QStringLiteral("QmlProfilerFlamegraph"));
@@ -66,22 +66,6 @@ FlameGraphView::FlameGraphView(QWidget *parent, QmlProfilerModelManager *manager
this, SIGNAL(gotoSourceLocation(QString,int,int)));
}
-void FlameGraphView::clear()
-{
- m_isRestrictedToRange = false;
-}
-
-void FlameGraphView::restrictToRange(qint64 rangeStart, qint64 rangeEnd)
-{
- m_isRestrictedToRange = (rangeStart != -1 || rangeEnd != -1);
- m_model->loadData(rangeStart, rangeEnd);
-}
-
-bool FlameGraphView::isRestrictedToRange() const
-{
- return m_isRestrictedToRange;
-}
-
void FlameGraphView::selectByTypeId(int typeIndex)
{
m_content->rootObject()->setProperty("selectedTypeId", typeIndex);
@@ -107,7 +91,7 @@ void FlameGraphView::contextMenuEvent(QContextMenuEvent *ev)
menu.addActions(QmlProfilerTool::profilerContextMenuActions());
menu.addSeparator();
getGlobalStatsAction = menu.addAction(tr("Show Full Range"));
- if (!isRestrictedToRange())
+ if (!m_model->modelManager()->isRestrictedToRange())
getGlobalStatsAction->setEnabled(false);
if (menu.exec(position) == getGlobalStatsAction)
diff --git a/src/plugins/qmlprofiler/flamegraphview.h b/src/plugins/qmlprofiler/flamegraphview.h
index 4acb1ac690..02b92723ed 100644
--- a/src/plugins/qmlprofiler/flamegraphview.h
+++ b/src/plugins/qmlprofiler/flamegraphview.h
@@ -40,10 +40,6 @@ class FlameGraphView : public QmlProfilerEventsView
public:
FlameGraphView(QWidget *parent, QmlProfilerModelManager *manager);
- void clear() override;
- void restrictToRange(qint64 rangeStart, qint64 rangeEnd) override;
- bool isRestrictedToRange() const override;
-
public slots:
void selectByTypeId(int typeIndex) override;
void onVisibleFeaturesChanged(quint64 features) override;
@@ -54,7 +50,6 @@ protected:
private:
QQuickWidget *m_content;
FlameGraphModel *m_model;
- bool m_isRestrictedToRange;
};
} // namespace Internal
diff --git a/src/plugins/qmlprofiler/memoryusagemodel.cpp b/src/plugins/qmlprofiler/memoryusagemodel.cpp
index 9ec47b694b..88bfbcb6ce 100644
--- a/src/plugins/qmlprofiler/memoryusagemodel.cpp
+++ b/src/plugins/qmlprofiler/memoryusagemodel.cpp
@@ -142,12 +142,12 @@ bool MemoryUsageModel::accepted(const QmlEventType &type) const
void MemoryUsageModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
{
- while (!m_rangeStack.empty() && m_rangeStack.top().endTime < event.timestamp())
- m_rangeStack.pop();
if (type.message != MemoryAllocation) {
if (type.rangeType != MaximumRangeType) {
- m_rangeStack.push(RangeStackFrame(event.typeIndex(), event.timestamp(),
- event.timestamp() + event.duration()));
+ if (event.rangeStage() == RangeStart)
+ m_rangeStack.push(RangeStackFrame(event.typeIndex(), event.timestamp()));
+ else if (event.rangeStage() == RangeEnd)
+ m_rangeStack.pop();
}
return;
}
diff --git a/src/plugins/qmlprofiler/memoryusagemodel.h b/src/plugins/qmlprofiler/memoryusagemodel.h
index 9cc1116823..1fb280323f 100644
--- a/src/plugins/qmlprofiler/memoryusagemodel.h
+++ b/src/plugins/qmlprofiler/memoryusagemodel.h
@@ -76,12 +76,11 @@ protected:
private:
struct RangeStackFrame {
- RangeStackFrame() : originTypeIndex(-1), startTime(-1), endTime(-1) {}
- RangeStackFrame(int originTypeIndex, qint64 startTime, qint64 endTime) :
- originTypeIndex(originTypeIndex), startTime(startTime), endTime(endTime) {}
+ RangeStackFrame() : originTypeIndex(-1), startTime(-1) {}
+ RangeStackFrame(int originTypeIndex, qint64 startTime) :
+ originTypeIndex(originTypeIndex), startTime(startTime) {}
int originTypeIndex;
qint64 startTime;
- qint64 endTime;
};
static QString memoryTypeName(int type);
diff --git a/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp b/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp
index ddd96da4f0..5263928da9 100644
--- a/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp
@@ -198,10 +198,6 @@ void QmlProfilerClientManager::connectClientSignals()
this, &QmlProfilerClientManager::qmlComplete);
connect(d->qmlclientplugin.data(), &QmlProfilerTraceClient::newEngine,
this, &QmlProfilerClientManager::qmlNewEngine);
- connect(d->qmlclientplugin.data(), &QmlProfilerTraceClient::rangedEvent,
- d->modelManager, &QmlProfilerModelManager::addQmlEvent);
- connect(d->qmlclientplugin.data(), &QmlProfilerTraceClient::debugMessage,
- d->modelManager, &QmlProfilerModelManager::addDebugMessage);
connect(d->qmlclientplugin.data(), &QmlProfilerTraceClient::traceFinished,
d->modelManager->traceTime(), &QmlProfilerTraceTime::increaseEndTime);
connect(d->qmlclientplugin.data(), &QmlProfilerTraceClient::traceStarted,
@@ -212,6 +208,8 @@ void QmlProfilerClientManager::connectClientSignals()
d->qmlclientplugin.data(), &QmlProfilerTraceClient::setRequestedFeatures);
connect(d->qmlclientplugin.data(), &QmlProfilerTraceClient::recordedFeaturesChanged,
d->profilerState, &QmlProfilerStateManager::setRecordedFeatures);
+ connect(d->qmlclientplugin.data(), &QmlProfilerTraceClient::qmlEvent,
+ d->modelManager, &QmlProfilerModelManager::addQmlEvent);
}
}
@@ -222,10 +220,6 @@ void QmlProfilerClientManager::disconnectClientSignals()
this, &QmlProfilerClientManager::qmlComplete);
disconnect(d->qmlclientplugin.data(), &QmlProfilerTraceClient::newEngine,
this, &QmlProfilerClientManager::qmlNewEngine);
- disconnect(d->qmlclientplugin.data(), &QmlProfilerTraceClient::rangedEvent,
- d->modelManager, &QmlProfilerModelManager::addQmlEvent);
- disconnect(d->qmlclientplugin.data(), &QmlProfilerTraceClient::debugMessage,
- d->modelManager, &QmlProfilerModelManager::addDebugMessage);
disconnect(d->qmlclientplugin.data(), &QmlProfilerTraceClient::traceFinished,
d->modelManager->traceTime(), &QmlProfilerTraceTime::increaseEndTime);
disconnect(d->qmlclientplugin.data(), &QmlProfilerTraceClient::traceStarted,
@@ -236,6 +230,8 @@ void QmlProfilerClientManager::disconnectClientSignals()
d->qmlclientplugin.data(), &QmlProfilerTraceClient::setRequestedFeatures);
disconnect(d->qmlclientplugin.data(), &QmlProfilerTraceClient::recordedFeaturesChanged,
d->profilerState, &QmlProfilerStateManager::setRecordedFeatures);
+ disconnect(d->qmlclientplugin.data(), &QmlProfilerTraceClient::qmlEvent,
+ d->modelManager, &QmlProfilerModelManager::addQmlEvent);
}
}
diff --git a/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp b/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp
index 870fcd7f4a..a54658ecf6 100644
--- a/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp
@@ -28,10 +28,12 @@
#include "qmlprofilernotesmodel.h"
#include "qmlprofilerdetailsrewriter.h"
#include "qmlprofilereventtypes.h"
+#include "qmltypedevent.h"
#include <utils/qtcassert.h>
#include <QUrl>
#include <QDebug>
+#include <QStack>
#include <algorithm>
namespace QmlProfiler {
@@ -39,10 +41,16 @@ namespace QmlProfiler {
class QmlProfilerDataModel::QmlProfilerDataModelPrivate
{
public:
+ void rewriteType(int typeIndex);
+ int resolveType(const QmlEventType &type);
+ int resolveStackTop();
+
QVector<QmlEventType> eventTypes;
QVector<QmlEvent> eventList;
QHash<QmlEventType, int> eventTypeIds;
+ QStack<QmlTypedEvent> rangesInProgress;
+
QmlProfilerModelManager *modelManager;
int modelId;
Internal::QmlProfilerDetailsRewriter *detailsRewriter;
@@ -108,9 +116,7 @@ QmlProfilerDataModel::QmlProfilerDataModel(Utils::FileInProjectFinder *fileFinde
connect(d->detailsRewriter, &QmlProfilerDetailsRewriter::rewriteDetailsString,
this, &QmlProfilerDataModel::detailsChanged);
connect(d->detailsRewriter, &QmlProfilerDetailsRewriter::eventDetailsChanged,
- this, &QmlProfilerDataModel::detailsDone);
- connect(this, &QmlProfilerDataModel::requestReload,
- d->detailsRewriter, &QmlProfilerDetailsRewriter::reloadDocuments);
+ this, &QmlProfilerDataModel::allTypesLoaded);
}
QmlProfilerDataModel::~QmlProfilerDataModel()
@@ -142,6 +148,9 @@ void QmlProfilerDataModel::setData(qint64 traceStart, qint64 traceEnd,
d->eventTypes = types;
for (int id = 0; id < types.count(); ++id)
d->eventTypeIds[types[id]] = id;
+
+ foreach (const QmlEvent &event, d->eventList)
+ d->modelManager->dispatch(event, d->eventTypes[event.typeIndex()]);
}
int QmlProfilerDataModel::count() const
@@ -156,6 +165,7 @@ void QmlProfilerDataModel::clear()
d->eventList.clear();
d->eventTypes.clear();
d->eventTypeIds.clear();
+ d->rangesInProgress.clear();
d->detailsRewriter->clearRequests();
}
@@ -165,11 +175,6 @@ bool QmlProfilerDataModel::isEmpty() const
return d->eventList.isEmpty();
}
-inline static bool operator<(const QmlEvent &t1, const QmlEvent &t2)
-{
- return t1.timestamp() < t2.timestamp();
-}
-
inline static uint qHash(const QmlEventType &type)
{
return qHash(type.location.filename) ^
@@ -190,66 +195,139 @@ inline static bool operator==(const QmlEventType &type1,
type1.location.filename == type2.location.filename;
}
-void QmlProfilerDataModel::processData()
+void QmlProfilerDataModel::QmlProfilerDataModelPrivate::rewriteType(int typeIndex)
{
- Q_D(QmlProfilerDataModel);
- // post-processing
-
- // sort events by start time, using above operator<
- std::sort(d->eventList.begin(), d->eventList.end());
+ QmlEventType &type = eventTypes[typeIndex];
+ type.displayName = getDisplayName(type);
+ type.data = getInitialDetails(type);
- // rewrite strings
- int n = d->eventTypes.count();
- for (int i = 0; i < n; i++) {
- QmlEventType *event = &d->eventTypes[i];
- event->displayName = getDisplayName(*event);
- event->data = getInitialDetails(*event);
+ // Only bindings and signal handlers need rewriting
+ if (type.rangeType != Binding && type.rangeType != HandlingSignal)
+ return;
- //
- // request further details from files
- //
+ // There is no point in looking for invalid locations
+ if (type.location.filename.isEmpty() || type.location.line < 0 || type.location.column < 0)
+ return;
- if (event->rangeType != Binding && event->rangeType != HandlingSignal)
- continue;
-
- // This skips anonymous bindings in Qt4.8 (we don't have valid location data for them)
- if (event->location.filename.isEmpty())
- continue;
+ detailsRewriter->requestDetailsForLocation(typeIndex, type.location);
+}
- // Skip non-anonymous bindings from Qt4.8 (we already have correct details for them)
- if (event->location.column == -1)
- continue;
+int QmlProfilerDataModel::QmlProfilerDataModelPrivate::resolveType(const QmlEventType &type)
+{
+ QHash<QmlEventType, int>::ConstIterator it = eventTypeIds.constFind(type);
- d->detailsRewriter->requestDetailsForLocation(i, event->location);
+ int typeIndex = -1;
+ if (it != eventTypeIds.constEnd()) {
+ typeIndex = it.value();
+ } else {
+ typeIndex = eventTypes.size();
+ eventTypeIds[type] = typeIndex;
+ eventTypes.append(type);
+ rewriteType(typeIndex);
}
+ return typeIndex;
+}
- emit requestReload();
+int QmlProfilerDataModel::QmlProfilerDataModelPrivate::resolveStackTop()
+{
+ if (rangesInProgress.isEmpty())
+ return -1;
+
+ QmlTypedEvent &typedEvent = rangesInProgress.top();
+ int typeIndex = typedEvent.event.typeIndex();
+ if (typeIndex >= 0)
+ return typeIndex;
+
+ typeIndex = resolveType(typedEvent.type);
+ typedEvent.event.setTypeIndex(typeIndex);
+ eventList.append(typedEvent.event);
+ modelManager->dispatch(eventList.last(), eventTypes[typeIndex]);
+ return typeIndex;
}
-void QmlProfilerDataModel::addEvent(Message message, RangeType rangeType, int detailType,
- qint64 startTime, qint64 duration, const QString &data,
- const QmlEventLocation &location, qint64 ndata1, qint64 ndata2,
- qint64 ndata3, qint64 ndata4, qint64 ndata5)
+void QmlProfilerDataModel::addEvent(const QmlEvent &event, const QmlEventType &type)
{
Q_D(QmlProfilerDataModel);
- QString displayName;
-
- QmlEventType typeData(displayName, location, message, rangeType, detailType,
- message == DebugMessage ? QString() : data);
- QmlEvent eventData = (message == DebugMessage) ?
- QmlEvent(startTime, duration, -1, data) :
- QmlEvent(startTime, duration, -1, {ndata1, ndata2, ndata3, ndata4, ndata5});
- QHash<QmlEventType, int>::Iterator it = d->eventTypeIds.find(typeData);
- if (it != d->eventTypeIds.end()) {
- eventData.setTypeIndex(it.value());
- } else {
- eventData.setTypeIndex(d->eventTypes.size());
- d->eventTypeIds[typeData] = eventData.typeIndex();
- d->eventTypes.append(typeData);
+ // RangeData and RangeLocation always apply to the range on the top of the stack. Furthermore,
+ // all ranges are perfectly nested. This is why we can defer the type resolution until either
+ // the range ends or a child range starts. With only the information in RangeStart we wouldn't
+ // be able to uniquely identify the event type.
+ Message rangeStage = type.rangeType == MaximumRangeType ? type.message : event.rangeStage();
+ switch (rangeStage) {
+ case RangeStart:
+ d->resolveStackTop();
+ d->rangesInProgress.push(QmlTypedEvent({event, type}));
+ break;
+ case RangeEnd: {
+ int typeIndex = d->resolveStackTop();
+ QTC_ASSERT(typeIndex != -1, break);
+ d->eventList.append(event);
+ QmlEvent &appended = d->eventList.last();
+ appended.setTypeIndex(typeIndex);
+ d->modelManager->dispatch(appended, d->eventTypes[typeIndex]);
+ d->rangesInProgress.pop();
+ break;
+ }
+ case RangeData:
+ d->rangesInProgress.top().type.data = type.data;
+ break;
+ case RangeLocation:
+ d->rangesInProgress.top().type.location = type.location;
+ break;
+ default: {
+ d->eventList.append(event);
+ QmlEvent &appended = d->eventList.last();
+ int typeIndex = d->resolveType(type);
+ appended.setTypeIndex(typeIndex);
+ d->modelManager->dispatch(appended, d->eventTypes[typeIndex]);
+ break;
}
+ }
+}
+
+void QmlProfilerDataModel::replayEvents(qint64 rangeStart, qint64 rangeEnd,
+ QmlProfilerModelManager::EventLoader loader) const
+{
+ Q_D(const QmlProfilerDataModel);
+ QStack<QmlEvent> stack;
+ foreach (const QmlEvent &event, d->eventList) {
+ const QmlEventType &type = d->eventTypes[event.typeIndex()];
+ if (rangeStart != -1 && rangeEnd != -1) {
+ if (event.timestamp() < rangeStart) {
+ if (type.rangeType != MaximumRangeType) {
+ if (event.rangeStage() == RangeStart)
+ stack.push(event);
+ else if (event.rangeStage() == RangeEnd)
+ stack.pop();
+ }
+ continue;
+ } else if (event.timestamp() > rangeEnd) {
+ if (type.rangeType != MaximumRangeType) {
+ if (event.rangeStage() == RangeEnd) {
+ if (stack.isEmpty()) {
+ QmlEvent endEvent(event);
+ endEvent.setTimestamp(rangeEnd);
+ loader(event, d->eventTypes[event.typeIndex()]);
+ } else {
+ stack.pop();
+ }
+ } else if (event.rangeStage() == RangeStart) {
+ stack.push(event);
+ }
+ }
+ continue;
+ } else if (!stack.isEmpty()) {
+ foreach (QmlEvent stashed, stack) {
+ stashed.setTimestamp(rangeStart);
+ loader(stashed, d->eventTypes[stashed.typeIndex()]);
+ }
+ stack.clear();
+ }
+ }
- d->eventList.append(eventData);
+ loader(event, type);
+ }
}
qint64 QmlProfilerDataModel::lastTimeMark() const
@@ -258,22 +336,20 @@ qint64 QmlProfilerDataModel::lastTimeMark() const
if (d->eventList.isEmpty())
return 0;
- return d->eventList.last().timestamp() + d->eventList.last().duration();
+ return d->eventList.last().timestamp();
}
-void QmlProfilerDataModel::detailsChanged(int requestId, const QString &newString)
+void QmlProfilerDataModel::finalize()
{
Q_D(QmlProfilerDataModel);
- QTC_ASSERT(requestId < d->eventTypes.count(), return);
-
- QmlEventType *event = &d->eventTypes[requestId];
- event->data = newString;
+ d->detailsRewriter->reloadDocuments();
}
-void QmlProfilerDataModel::detailsDone()
+void QmlProfilerDataModel::detailsChanged(int requestId, const QString &newString)
{
Q_D(QmlProfilerDataModel);
- d->modelManager->processingDone();
+ QTC_ASSERT(requestId < d->eventTypes.count(), return);
+ d->eventTypes[requestId].data = newString;
}
} // namespace QmlProfiler
diff --git a/src/plugins/qmlprofiler/qmlprofilerdatamodel.h b/src/plugins/qmlprofiler/qmlprofilerdatamodel.h
index 6f7bce387f..5ab239b909 100644
--- a/src/plugins/qmlprofiler/qmlprofilerdatamodel.h
+++ b/src/plugins/qmlprofiler/qmlprofilerdatamodel.h
@@ -49,22 +49,21 @@ public:
const QVector<QmlEventType> &eventTypes() const;
void setData(qint64 traceStart, qint64 traceEnd, const QVector<QmlEventType> &types,
const QVector<QmlEvent> &events);
- void processData();
int count() const;
void clear();
bool isEmpty() const;
- void addEvent(Message message, RangeType rangeType, int bindingType, qint64 startTime,
- qint64 duration, const QString &data, const QmlEventLocation &location,
- qint64 ndata1, qint64 ndata2, qint64 ndata3, qint64 ndata4, qint64 ndata5);
+ void addEvent(const QmlEvent &event, const QmlEventType &type);
+ void replayEvents(qint64 startTime, qint64 endTime,
+ QmlProfilerModelManager::EventLoader loader) const;
+ void finalize();
qint64 lastTimeMark() const;
signals:
- void requestReload();
+ void allTypesLoaded();
protected slots:
void detailsChanged(int requestId, const QString &newString);
- void detailsDone();
private:
class QmlProfilerDataModelPrivate;
diff --git a/src/plugins/qmlprofiler/qmlprofilereventsview.h b/src/plugins/qmlprofiler/qmlprofilereventsview.h
index 9406c8e971..e48f64ab95 100644
--- a/src/plugins/qmlprofiler/qmlprofilereventsview.h
+++ b/src/plugins/qmlprofiler/qmlprofilereventsview.h
@@ -38,10 +38,7 @@ class QMLPROFILER_EXPORT QmlProfilerEventsView : public QWidget
Q_OBJECT
public:
QmlProfilerEventsView(QWidget *parent = 0) : QWidget(parent) {}
-
- virtual void clear() = 0;
- virtual void restrictToRange(qint64 rangeStart, qint64 rangeEnd) = 0;
- virtual bool isRestrictedToRange() const = 0;
+ virtual void clear() {}
signals:
void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber);
diff --git a/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp
index e3832d226b..f4b39c63b8 100644
--- a/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp
@@ -37,6 +37,8 @@
#include <QFile>
#include <QMessageBox>
+#include <functional>
+
namespace QmlProfiler {
namespace Internal {
@@ -59,22 +61,19 @@ Q_STATIC_ASSERT(sizeof(ProfileFeatureNames) == sizeof(char *) * MaximumProfileFe
/////////////////////////////////////////////////////////////////////
QmlProfilerTraceTime::QmlProfilerTraceTime(QObject *parent) :
- QObject(parent), m_startTime(-1), m_endTime(-1)
-{
-}
-
-QmlProfilerTraceTime::~QmlProfilerTraceTime()
+ QObject(parent), m_startTime(-1), m_endTime(-1),
+ m_restrictedStartTime(-1), m_restrictedEndTime(-1)
{
}
qint64 QmlProfilerTraceTime::startTime() const
{
- return m_startTime;
+ return m_restrictedStartTime != -1 ? m_restrictedStartTime : m_startTime;
}
qint64 QmlProfilerTraceTime::endTime() const
{
- return m_endTime;
+ return m_restrictedEndTime != -1 ? m_restrictedEndTime : m_endTime;
}
qint64 QmlProfilerTraceTime::duration() const
@@ -82,18 +81,22 @@ qint64 QmlProfilerTraceTime::duration() const
return endTime() - startTime();
}
+bool QmlProfilerTraceTime::isRestrictedToRange() const
+{
+ return m_restrictedStartTime != -1 || m_restrictedEndTime != -1;
+}
+
void QmlProfilerTraceTime::clear()
{
+ restrictToRange(-1, -1);
setTime(-1, -1);
}
void QmlProfilerTraceTime::setTime(qint64 startTime, qint64 endTime)
{
- Q_ASSERT(startTime <= endTime);
- if (startTime != m_startTime || endTime != m_endTime) {
- m_startTime = startTime;
- m_endTime = endTime;
- }
+ QTC_ASSERT(startTime <= endTime, endTime = startTime);
+ m_startTime = startTime;
+ m_endTime = endTime;
}
void QmlProfilerTraceTime::decreaseStartTime(qint64 time)
@@ -118,6 +121,13 @@ void QmlProfilerTraceTime::increaseEndTime(qint64 time)
}
}
+void QmlProfilerTraceTime::restrictToRange(qint64 startTime, qint64 endTime)
+{
+ QTC_ASSERT(endTime == -1 || startTime <= endTime, endTime = startTime);
+ m_restrictedStartTime = startTime;
+ m_restrictedEndTime = endTime;
+}
+
} // namespace Internal
@@ -153,6 +163,8 @@ QmlProfilerModelManager::QmlProfilerModelManager(Utils::FileInProjectFinder *fin
d->state = Empty;
d->traceTime = new QmlProfilerTraceTime(this);
d->notesModel = new QmlProfilerNotesModel(this);
+ connect(d->model, &QmlProfilerDataModel::allTypesLoaded,
+ this, &QmlProfilerModelManager::processingDone);
}
QmlProfilerModelManager::~QmlProfilerModelManager()
@@ -247,34 +259,17 @@ const char *QmlProfilerModelManager::featureName(ProfileFeature feature)
return ProfileFeatureNames[feature];
}
-void QmlProfilerModelManager::addQmlEvent(Message message, RangeType rangeType, int detailType,
- qint64 startTime, qint64 length, const QString &data,
- const QmlEventLocation &location, qint64 ndata1,
- qint64 ndata2, qint64 ndata3, qint64 ndata4,
- qint64 ndata5)
-{
- // If trace start time was not explicitly set, use the first event
- if (d->traceTime->startTime() == -1)
- d->traceTime->setTime(startTime, startTime + d->traceTime->duration());
-
- QTC_ASSERT(state() == AcquiringData, /**/);
- d->model->addEvent(message, rangeType, detailType, startTime, length, data, location, ndata1,
- ndata2, ndata3, ndata4, ndata5);
-}
-
-void QmlProfilerModelManager::addDebugMessage(qint64 timestamp, QtMsgType messageType,
- const QString &text, const QmlEventLocation &location)
+void QmlProfilerModelManager::addQmlEvent(const QmlEvent &event, const QmlEventType &type)
{
- if (state() == AcquiringData)
- d->model->addEvent(DebugMessage, MaximumRangeType, messageType, timestamp, 0, text,
- location, 0, 0, 0, 0, 0);
+ QTC_ASSERT(state() == AcquiringData, return);
+ d->model->addEvent(event, type);
}
void QmlProfilerModelManager::acquiringDone()
{
QTC_ASSERT(state() == AcquiringData, /**/);
setState(ProcessingData);
- d->model->processData();
+ d->model->finalize();
}
void QmlProfilerModelManager::processingDone()
@@ -282,8 +277,13 @@ void QmlProfilerModelManager::processingDone()
QTC_ASSERT(state() == ProcessingData, /**/);
// Load notes after the timeline models have been initialized ...
// which happens on stateChanged(Done).
- setState(Done);
+
+ foreach (const Finalizer &finalizer, d->finalizers)
+ finalizer();
+
d->notesModel->loadData();
+ setState(Done);
+
emit loadFinished();
}
@@ -408,6 +408,26 @@ void QmlProfilerModelManager::clear()
setState(Empty);
}
+void QmlProfilerModelManager::restrictToRange(qint64 startTime, qint64 endTime)
+{
+ setState(ClearingData);
+ d->notesModel->saveData();
+ setVisibleFeatures(0);
+
+ startAcquiring();
+ d->model->replayEvents(startTime, endTime,
+ std::bind(&QmlProfilerModelManager::dispatch, this,
+ std::placeholders::_1, std::placeholders::_2));
+ d->notesModel->loadData();
+ d->traceTime->restrictToRange(startTime, endTime);
+ acquiringDone();
+}
+
+bool QmlProfilerModelManager::isRestrictedToRange() const
+{
+ return d->traceTime->isRestrictedToRange();
+}
+
void QmlProfilerModelManager::startAcquiring()
{
setState(AcquiringData);
diff --git a/src/plugins/qmlprofiler/qmlprofilermodelmanager.h b/src/plugins/qmlprofiler/qmlprofilermodelmanager.h
index 92e5f7872c..c796bd65a5 100644
--- a/src/plugins/qmlprofiler/qmlprofilermodelmanager.h
+++ b/src/plugins/qmlprofiler/qmlprofilermodelmanager.h
@@ -48,11 +48,11 @@ class QMLPROFILER_EXPORT QmlProfilerTraceTime : public QObject
Q_OBJECT
public:
explicit QmlProfilerTraceTime(QObject *parent);
- ~QmlProfilerTraceTime();
qint64 startTime() const;
qint64 endTime() const;
qint64 duration() const;
+ bool isRestrictedToRange() const;
public slots:
void clear();
@@ -60,10 +60,14 @@ public slots:
void setTime(qint64 startTime, qint64 endTime);
void decreaseStartTime(qint64 time);
void increaseEndTime(qint64 time);
+ void restrictToRange(qint64 startTime, qint64 endTime);
private:
qint64 m_startTime;
qint64 m_endTime;
+
+ qint64 m_restrictedStartTime;
+ qint64 m_restrictedEndTime;
};
} // End internal namespace
@@ -124,13 +128,11 @@ signals:
public slots:
void clear();
+ void restrictToRange(qint64 startTime, qint64 endTime);
+ bool isRestrictedToRange() const;
void startAcquiring();
- void addQmlEvent(Message message, RangeType rangeType, int bindingType, qint64 startTime,
- qint64 length, const QString &data, const QmlEventLocation &location,
- qint64 ndata1, qint64 ndata2, qint64 ndata3, qint64 ndata4, qint64 ndata5);
- void addDebugMessage(qint64 timestamp, QtMsgType type, const QString &text,
- const QmlEventLocation &location);
+ void addQmlEvent(const QmlEvent &event, const QmlEventType &type);
void save(const QString &filename);
void load(const QString &filename);
diff --git a/src/plugins/qmlprofiler/qmlprofilerrangemodel.cpp b/src/plugins/qmlprofiler/qmlprofilerrangemodel.cpp
index 2119e94b7f..4c174dbc74 100644
--- a/src/plugins/qmlprofiler/qmlprofilerrangemodel.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerrangemodel.cpp
@@ -54,6 +54,7 @@ void QmlProfilerRangeModel::clear()
m_expandedRowTypes.clear();
m_expandedRowTypes << -1;
m_data.clear();
+ m_stack.clear();
QmlProfilerTimelineModel::clear();
}
@@ -66,8 +67,14 @@ void QmlProfilerRangeModel::loadEvent(const QmlEvent &event, const QmlEventType
{
Q_UNUSED(type);
// store starttime-based instance
- m_data.insert(insert(event.timestamp(), event.duration(), event.typeIndex()),
- QmlRangeEventStartInstance());
+ if (event.rangeStage() == RangeStart) {
+ int index = insertStart(event.timestamp(), event.typeIndex());
+ m_stack.append(index);
+ m_data.insert(index, QmlRangeEventStartInstance());
+ } else if (event.rangeStage() == RangeEnd) {
+ int index = m_stack.pop();
+ insertEnd(index, event.timestamp() - startTime(index));
+ }
}
void QmlProfilerRangeModel::finalize()
diff --git a/src/plugins/qmlprofiler/qmlprofilerrangemodel.h b/src/plugins/qmlprofiler/qmlprofilerrangemodel.h
index 3b2af9dba8..553bdb89c7 100644
--- a/src/plugins/qmlprofiler/qmlprofilerrangemodel.h
+++ b/src/plugins/qmlprofiler/qmlprofilerrangemodel.h
@@ -33,6 +33,7 @@
#include <QVariantList>
#include <QColor>
+#include <QStack>
namespace QmlProfiler {
class QmlProfilerModelManager;
@@ -85,6 +86,7 @@ private:
void findBindingLoops();
QVector<QmlRangeEventStartInstance> m_data;
+ QStack<int> m_stack;
QVector<int> m_expandedRowTypes;
};
diff --git a/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp b/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp
index ae4d59961c..6833e20548 100644
--- a/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp
@@ -37,12 +37,17 @@
#include <QSet>
#include <QPointer>
+#include <functional>
+
namespace QmlProfiler {
class QmlProfilerStatisticsModel::QmlProfilerStatisticsModelPrivate
{
public:
QHash<int, QmlProfilerStatisticsModel::QmlEventStats> data;
+ QHash<int, QmlProfilerStatisticsModel::QmlEventStats> workingSet;
+
+
QPointer<QmlProfilerStatisticsRelativesModel> childrenModel;
QPointer<QmlProfilerStatisticsRelativesModel> parentsModel;
@@ -87,12 +92,34 @@ QmlProfilerStatisticsModel::~QmlProfilerStatisticsModel()
delete d;
}
-void QmlProfilerStatisticsModel::setEventTypeAccepted(RangeType type, bool accepted)
+void QmlProfilerStatisticsModel::restrictToFeatures(qint64 features)
{
- if (accepted && !d->acceptedTypes.contains(type))
- d->acceptedTypes << type;
- else if (!accepted && d->acceptedTypes.contains(type))
- d->acceptedTypes.removeOne(type);
+ bool didChange = false;
+ for (int i = 0; i < MaximumRangeType; ++i) {
+ RangeType type = static_cast<RangeType>(i);
+ quint64 featureFlag = 1ULL << featureFromRangeType(type);
+ if (Constants::QML_JS_RANGE_FEATURES & featureFlag) {
+ bool accepted = features & featureFlag;
+ if (accepted && !d->acceptedTypes.contains(type)) {
+ d->acceptedTypes << type;
+ didChange = true;
+ } else if (!accepted && d->acceptedTypes.contains(type)) {
+ d->acceptedTypes.removeOne(type);
+ didChange = true;
+ }
+ }
+ }
+ if (!didChange || d->modelManager->state() != QmlProfilerModelManager::Done)
+ return;
+
+ clear();
+ d->modelManager->qmlModel()->replayEvents(d->modelManager->traceTime()->startTime(),
+ d->modelManager->traceTime()->endTime(),
+ std::bind(&QmlProfilerStatisticsModel::loadEvent,
+ this, std::placeholders::_1,
+ std::placeholders::_2));
+ finalize();
+ notesChanged(-1); // Reload notes
}
const QHash<int, QmlProfilerStatisticsModel::QmlEventStats> &QmlProfilerStatisticsModel::getData() const
@@ -126,12 +153,6 @@ void QmlProfilerStatisticsModel::clear()
d->parentsModel->clear();
}
-void QmlProfilerStatisticsModel::limitToRange(qint64 rangeStart, qint64 rangeEnd)
-{
- if (!d->modelManager->isEmpty())
- loadData(rangeStart, rangeEnd);
-}
-
void QmlProfilerStatisticsModel::setRelativesModel(QmlProfilerStatisticsRelativesModel *relative,
QmlProfilerStatisticsRelation relation)
{
@@ -141,11 +162,14 @@ void QmlProfilerStatisticsModel::setRelativesModel(QmlProfilerStatisticsRelative
d->childrenModel = relative;
}
+QmlProfilerModelManager *QmlProfilerStatisticsModel::modelManager() const
+{
+ return d->modelManager;
+}
+
void QmlProfilerStatisticsModel::dataChanged()
{
- if (d->modelManager->state() == QmlProfilerModelManager::ProcessingData)
- loadData();
- else if (d->modelManager->state() == QmlProfilerModelManager::ClearingData)
+ if (d->modelManager->state() == QmlProfilerModelManager::ClearingData)
clear();
}
@@ -181,80 +205,53 @@ void QmlProfilerStatisticsModel::notesChanged(int typeIndex)
emit notesAvailable(typeIndex);
}
-void QmlProfilerStatisticsModel::loadData(qint64 rangeStart, qint64 rangeEnd)
-{
- clear();
-
- const bool checkRanges = (rangeStart != -1) && (rangeEnd != -1);
-
- const QVector<QmlEvent> &eventList = d->modelManager->qmlModel()->events();
- const QVector<QmlEventType> &typesList = d->modelManager->qmlModel()->eventTypes();
-
- for (int i = 0; i < eventList.size(); ++i) {
- const QmlEvent &event = eventList[i];
- const QmlEventType &type = typesList[event.typeIndex()];
-
- if (checkRanges) {
- if ((event.timestamp() + event.duration() < rangeStart)
- || (event.timestamp() > rangeEnd))
- continue;
- }
-
- loadEvent(event, type);
- }
-
- finalize();
- if (checkRanges)
- notesChanged(-1); // Reload notes
-}
-
void QmlProfilerStatisticsModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
{
if (!d->acceptedTypes.contains(type.rangeType))
return;
- // update stats
- QmlEventStats *stats = &d->data[event.typeIndex()];
-
- stats->duration += event.duration();
- stats->durationSelf += event.duration();
- if (event.duration() < stats->minTime)
- stats->minTime = event.duration();
- if (event.duration() > stats->maxTime)
- stats->maxTime = event.duration();
- stats->calls++;
+ switch (event.rangeStage()) {
+ case RangeStart:
+ // binding loop detection: check whether event is already in stack
+ for (int ii = 1; ii < d->callStack.size(); ++ii) {
+ if (d->callStack.at(ii).typeIndex() == event.typeIndex()
+ && type.rangeType != Javascript) {
+ d->eventsInBindingLoop.insert(event.typeIndex());
+ break;
+ }
+ }
+ d->callStack.push(event);
+ break;
+ case RangeEnd: {
+ // update stats
+ QmlEventStats *stats = &d->data[event.typeIndex()];
+ qint64 duration = event.timestamp() - d->callStack.top().timestamp();
+ stats->duration += duration;
+ stats->durationSelf += duration;
+ if (duration < stats->minTime)
+ stats->minTime = duration;
+ if (duration > stats->maxTime)
+ stats->maxTime = duration;
+ stats->calls++;
+ // for median computing
+ d->durations[event.typeIndex()].append(duration);
+ // qml time computation
+ if (event.timestamp() > d->lastEndTime) { // assume parent event if starts before last end
+ d->qmlTime += duration;
+ d->lastEndTime = event.timestamp();
+ }
- // for median computing
- d->durations[event.typeIndex()].append(event.duration());
+ d->callStack.pop();
- // qml time computation
- if (event.timestamp() > d->lastEndTime) { // assume parent event if starts before last end
- d->qmlTime += event.duration();
- d->lastEndTime = event.timestamp() + event.duration();
- }
+ if (d->callStack.count() > 1)
+ d->data[d->callStack.top().typeIndex()].durationSelf -= duration;
- //
- // binding loop detection
- //
- const QmlEvent *potentialParent = &(d->callStack.top());
- while (potentialParent->isValid() &&
- !(potentialParent->timestamp() + potentialParent->duration() > event.timestamp())) {
- d->callStack.pop();
- potentialParent = &(d->callStack.top());
+ break;
}
-
- // check whether event is already in stack
- for (int ii = 1; ii < d->callStack.size(); ++ii) {
- if (d->callStack.at(ii).typeIndex() == event.typeIndex()) {
- d->eventsInBindingLoop.insert(event.typeIndex());
- break;
- }
+ default:
+ break;
}
- if (d->callStack.count() > 1)
- d->data[d->callStack.top().typeIndex()].durationSelf -= event.duration();
- d->callStack.push(event);
-
if (!d->childrenModel.isNull())
d->childrenModel->loadEvent(event);
if (!d->parentsModel.isNull())
@@ -294,6 +291,7 @@ void QmlProfilerStatisticsModel::finalize()
rootEvent.percentSelf = 1.0 / rootEvent.duration;
d->data.insert(-1, rootEvent);
+
if (!d->childrenModel.isNull())
d->childrenModel->finalize(d->eventsInBindingLoop);
if (!d->parentsModel.isNull())
@@ -312,7 +310,7 @@ QmlProfilerStatisticsRelativesModel::QmlProfilerStatisticsRelativesModel(
QmlProfilerStatisticsRelation relation, QObject *parent) :
QObject(parent), m_relation(relation)
{
- m_endtimesPerLevel[0] = 0;
+ m_startTimesPerLevel[0] = 0;
QTC_CHECK(modelManager);
m_modelManager = modelManager;
@@ -346,40 +344,42 @@ const QVector<QmlEventType> &QmlProfilerStatisticsRelativesModel::getTypes() con
void QmlProfilerStatisticsRelativesModel::loadEvent(const QmlEvent &event)
{
// level computation
- if (m_endtimesPerLevel[m_level] > event.timestamp()) {
- m_level++;
- } else {
- while (m_level > Constants::QML_MIN_LEVEL &&
- m_endtimesPerLevel[m_level-1] <= event.timestamp())
- m_level--;
+ switch (event.rangeStage()) {
+ case RangeStart:
+ // now lastparent is the new type
+ ++m_level;
+ m_typesPerLevel[m_level] = event.typeIndex();
+ m_startTimesPerLevel[m_level] = event.timestamp();
+ break;
+ case RangeEnd: {
+ int parentTypeIndex = -1;
+ if (m_level > Constants::QML_MIN_LEVEL && m_typesPerLevel.contains(m_level-1))
+ parentTypeIndex = m_typesPerLevel[m_level-1];
+
+ int relativeTypeIndex = (m_relation == QmlProfilerStatisticsParents) ? parentTypeIndex :
+ event.typeIndex();
+ int selfTypeIndex = (m_relation == QmlProfilerStatisticsParents) ? event.typeIndex() :
+ parentTypeIndex;
+
+ QmlStatisticsRelativesMap &relativesMap = m_data[selfTypeIndex];
+ QmlStatisticsRelativesMap::Iterator it = relativesMap.find(relativeTypeIndex);
+ if (it != relativesMap.end()) {
+ it.value().calls++;
+ it.value().duration += event.timestamp() - m_startTimesPerLevel[m_level];
+ } else {
+ QmlStatisticsRelativesData relative = {
+ event.timestamp() - m_startTimesPerLevel[m_level],
+ 1,
+ false
+ };
+ relativesMap.insert(relativeTypeIndex, relative);
+ }
+ --m_level;
+ break;
}
- m_endtimesPerLevel[m_level] = event.timestamp() + event.duration();
-
- int parentTypeIndex = -1;
- if (m_level > Constants::QML_MIN_LEVEL && m_lastParent.contains(m_level-1))
- parentTypeIndex = m_lastParent[m_level-1];
-
- int relativeTypeIndex = (m_relation == QmlProfilerStatisticsParents) ? parentTypeIndex :
- event.typeIndex();
- int selfTypeIndex = (m_relation == QmlProfilerStatisticsParents) ? event.typeIndex() :
- parentTypeIndex;
-
- QmlStatisticsRelativesMap &relativesMap = m_data[selfTypeIndex];
- QmlStatisticsRelativesMap::Iterator it = relativesMap.find(relativeTypeIndex);
- if (it != relativesMap.end()) {
- it.value().calls++;
- it.value().duration += event.duration();
- } else {
- QmlStatisticsRelativesData relative = {
- event.duration(),
- 1,
- false
- };
- relativesMap.insert(relativeTypeIndex, relative);
+ default:
+ break;
}
-
- // now lastparent is the new type
- m_lastParent[m_level] = event.typeIndex();
}
void QmlProfilerStatisticsRelativesModel::finalize(const QSet<int> &eventsInBindingLoop)
@@ -402,10 +402,10 @@ int QmlProfilerStatisticsRelativesModel::count() const
void QmlProfilerStatisticsRelativesModel::clear()
{
m_data.clear();
- m_endtimesPerLevel.clear();
+ m_startTimesPerLevel.clear();
m_level = Constants::QML_MIN_LEVEL;
- m_endtimesPerLevel[0] = 0;
- m_lastParent.clear();
+ m_startTimesPerLevel[0] = 0;
+ m_typesPerLevel.clear();
}
} // namespace QmlProfiler
diff --git a/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.h b/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.h
index 6c28116ad1..6cc357fe68 100644
--- a/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.h
+++ b/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.h
@@ -68,7 +68,7 @@ public:
QmlProfilerStatisticsModel(QmlProfilerModelManager *modelManager, QObject *parent = 0);
~QmlProfilerStatisticsModel();
- void setEventTypeAccepted(RangeType type, bool accepted);
+ void restrictToFeatures(qint64 features);
const QHash<int, QmlEventStats> &getData() const;
const QVector<QmlEventType> &getTypes() const;
@@ -77,16 +77,15 @@ public:
int count() const;
void clear();
- void limitToRange(qint64 rangeStart, qint64 rangeEnd);
void setRelativesModel(QmlProfilerStatisticsRelativesModel *childModel,
QmlProfilerStatisticsRelation relation);
+ QmlProfilerModelManager *modelManager() const;
signals:
void dataAvailable();
void notesAvailable(int typeIndex);
private:
- void loadData(qint64 rangeStart = -1, qint64 rangeEnd = -1);
void loadEvent(const QmlEvent &event, const QmlEventType &type);
void finalize();
@@ -133,11 +132,11 @@ protected:
QmlProfilerModelManager *m_modelManager;
// for level computation
- QHash<int, qint64> m_endtimesPerLevel;
+ QHash<int, qint64> m_startTimesPerLevel;
int m_level = Constants::QML_MIN_LEVEL;
// compute parent-child relationship and call count
- QHash<int, int> m_lastParent;
+ QHash<int, int> m_typesPerLevel;
const QmlProfilerStatisticsRelation m_relation;
};
diff --git a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp
index 579cafc0c3..3bc34f471c 100644
--- a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp
@@ -110,8 +110,6 @@ public:
QmlProfilerStatisticsRelativesView *m_eventParents;
QmlProfilerStatisticsModel *model;
- qint64 rangeStart;
- qint64 rangeEnd;
};
static void setViewDefaults(Utils::TreeView *view)
@@ -228,8 +226,6 @@ QmlProfilerStatisticsView::QmlProfilerStatisticsView(QWidget *parent,
splitterVertical->setStretchFactor(1,2);
groupLayout->addWidget(splitterVertical);
setLayout(groupLayout);
-
- d->rangeStart = d->rangeEnd = -1;
}
QmlProfilerStatisticsView::~QmlProfilerStatisticsView()
@@ -243,14 +239,6 @@ void QmlProfilerStatisticsView::clear()
d->m_eventTree->clear();
d->m_eventChildren->clear();
d->m_eventParents->clear();
- d->rangeStart = d->rangeEnd = -1;
-}
-
-void QmlProfilerStatisticsView::restrictToRange(qint64 rangeStart, qint64 rangeEnd)
-{
- d->rangeStart = rangeStart;
- d->rangeEnd = rangeEnd;
- d->model->limitToRange(rangeStart, rangeEnd);
}
QModelIndex QmlProfilerStatisticsView::selectedModelIndex() const
@@ -285,7 +273,7 @@ void QmlProfilerStatisticsView::contextMenuEvent(QContextMenuEvent *ev)
menu.addSeparator();
getGlobalStatsAction = menu.addAction(tr("Show Full Range"));
- if (!isRestrictedToRange())
+ if (!d->model->modelManager()->isRestrictedToRange())
getGlobalStatsAction->setEnabled(false);
QAction *selectedAction = menu.exec(position);
@@ -327,18 +315,7 @@ void QmlProfilerStatisticsView::selectByTypeId(int typeIndex)
void QmlProfilerStatisticsView::onVisibleFeaturesChanged(quint64 features)
{
- for (int i = 0; i < MaximumRangeType; ++i) {
- RangeType range = static_cast<RangeType>(i);
- quint64 featureFlag = 1ULL << featureFromRangeType(range);
- if (Constants::QML_JS_RANGE_FEATURES & featureFlag)
- d->model->setEventTypeAccepted(range, features & featureFlag);
- }
- d->model->limitToRange(d->rangeStart, d->rangeEnd);
-}
-
-bool QmlProfilerStatisticsView::isRestrictedToRange() const
-{
- return d->rangeStart != -1 || d->rangeEnd != -1;
+ d->model->restrictToFeatures(features);
}
void QmlProfilerStatisticsView::setShowExtendedStatistics(bool show)
diff --git a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.h b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.h
index 0bde5adbec..9b5a693b8c 100644
--- a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.h
+++ b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.h
@@ -78,10 +78,7 @@ public:
explicit QmlProfilerStatisticsView(QWidget *parent,
QmlProfilerModelManager *profilerModelManager);
~QmlProfilerStatisticsView();
-
void clear() override;
- void restrictToRange(qint64 rangeStart, qint64 rangeEnd) override;
- bool isRestrictedToRange() const override;
public slots:
void selectByTypeId(int typeIndex) override;
diff --git a/src/plugins/qmlprofiler/qmlprofilertimelinemodel.cpp b/src/plugins/qmlprofiler/qmlprofilertimelinemodel.cpp
index 31d3c81ba0..2500f1ac4b 100644
--- a/src/plugins/qmlprofiler/qmlprofilertimelinemodel.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertimelinemodel.cpp
@@ -95,7 +95,6 @@ void QmlProfilerTimelineModel::dataChanged()
switch (m_modelManager->state()) {
case QmlProfilerModelManager::Done:
- loadData();
emit emptyChanged();
break;
case QmlProfilerModelManager::ClearingData:
@@ -139,21 +138,4 @@ QVariantMap QmlProfilerTimelineModel::locationFromTypeId(int index) const
return result;
}
-void QmlProfilerTimelineModel::loadData()
-{
- QmlProfilerDataModel *simpleModel = modelManager()->qmlModel();
- if (simpleModel->isEmpty())
- return;
-
- const QVector<QmlEventType> &types = simpleModel->eventTypes();
-
- foreach (const QmlEvent &event, simpleModel->events()) {
- const QmlEventType &type = types[event.typeIndex()];
- if (accepted(type)) {
- loadEvent(event, type);
- }
- }
- finalize();
-}
-
} // namespace QmlProfiler
diff --git a/src/plugins/qmlprofiler/qmlprofilertimelinemodel.h b/src/plugins/qmlprofiler/qmlprofilertimelinemodel.h
index fa9255efee..c5097e8629 100644
--- a/src/plugins/qmlprofiler/qmlprofilertimelinemodel.h
+++ b/src/plugins/qmlprofiler/qmlprofilertimelinemodel.h
@@ -53,8 +53,6 @@ public:
Q_INVOKABLE virtual int bindingLoopDest(int index) const;
QVariantMap locationFromTypeId(int index) const;
- void loadData();
-
virtual void loadEvent(const QmlEvent &event, const QmlEventType &type) = 0;
virtual void finalize() = 0;
void clear();
diff --git a/src/plugins/qmlprofiler/qmlprofilertraceclient.cpp b/src/plugins/qmlprofiler/qmlprofilertraceclient.cpp
index ce3b82c578..ab2eb291f6 100644
--- a/src/plugins/qmlprofiler/qmlprofilertraceclient.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertraceclient.cpp
@@ -24,6 +24,8 @@
****************************************************************************/
#include "qmlprofilertraceclient.h"
+#include "qmltypedevent.h"
+
#include <qmldebug/qmlenginecontrolclient.h>
#include <qmldebug/qdebugmessageclient.h>
#include <qmldebug/qpacketprotocol.h>
@@ -35,14 +37,12 @@ public:
QmlProfilerTraceClientPrivate(QmlProfilerTraceClient *_q, QmlDebug::QmlDebugConnection *client)
: q(_q)
, engineControl(client)
- , inProgressRanges(0)
, maximumTime(0)
, recording(false)
, requestedFeatures(0)
, recordedFeatures(0)
, flushInterval(0)
{
- ::memset(rangeCount, 0, MaximumRangeType * sizeof(int));
}
void sendRecordingStatus(int engineId);
@@ -51,17 +51,14 @@ public:
QmlProfilerTraceClient *q;
QmlDebug::QmlEngineControlClient engineControl;
QScopedPointer<QmlDebug::QDebugMessageClient> messageClient;
- qint64 inProgressRanges;
- QStack<qint64> rangeStartTimes[MaximumRangeType];
- QStack<QString> rangeDatas[MaximumRangeType];
- QStack<QmlEventLocation> rangeLocations[MaximumRangeType];
- QStack<BindingType> bindingTypes;
- int rangeCount[MaximumRangeType];
qint64 maximumTime;
bool recording;
quint64 requestedFeatures;
quint64 recordedFeatures;
quint32 flushInterval;
+
+ // Reuse the same event, so that we don't have to constantly reallocate all the data.
+ QmlTypedEvent currentEvent;
};
void QmlProfilerTraceClientPrivate::sendRecordingStatus(int engineId)
@@ -94,13 +91,6 @@ QmlProfilerTraceClient::~QmlProfilerTraceClient()
void QmlProfilerTraceClient::clearData()
{
- ::memset(d->rangeCount, 0, MaximumRangeType * sizeof(int));
- for (int eventType = 0; eventType < MaximumRangeType; eventType++) {
- d->rangeDatas[eventType].clear();
- d->rangeLocations[eventType].clear();
- d->rangeStartTimes[eventType].clear();
- }
- d->bindingTypes.clear();
if (d->recordedFeatures != 0) {
d->recordedFeatures = 0;
emit recordedFeaturesChanged(0);
@@ -146,8 +136,18 @@ void QmlProfilerTraceClient::setRequestedFeatures(quint64 features)
const QmlDebug::QDebugContextInfo &context)
{
d->updateFeatures(ProfileDebugMessages);
- emit debugMessage(context.timestamp, type, text,
- QmlEventLocation(context.file, context.line, 1));
+ d->currentEvent.event.setTimestamp(context.timestamp);
+ d->currentEvent.event.setTypeIndex(-1);
+ d->currentEvent.event.setString(text);
+ d->currentEvent.type.location.filename = context.file;
+ d->currentEvent.type.location.line = context.line;
+ d->currentEvent.type.location.column = 1;
+ d->currentEvent.type.displayName.clear();
+ d->currentEvent.type.data.clear();
+ d->currentEvent.type.message = DebugMessage;
+ d->currentEvent.type.rangeType = MaximumRangeType;
+ d->currentEvent.type.detailType = type;
+ emit qmlEvent(d->currentEvent.event, d->currentEvent.type);
});
} else {
d->messageClient.reset();
@@ -189,210 +189,24 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
{
QmlDebug::QPacket stream(connection()->currentDataStreamVersion(), data);
- qint64 time;
- int messageType;
- int subtype;
-
- stream >> time >> messageType;
- if (!stream.atEnd())
- stream >> subtype;
- else
- subtype = -1;
-
- switch (messageType) {
- case Event: {
- switch (subtype) {
- case StartTrace: {
- if (!d->recording)
- setRecordingFromServer(true);
- QList<int> engineIds;
- while (!stream.atEnd()) {
- int id;
- stream >> id;
- engineIds << id;
- }
- emit traceStarted(time, engineIds);
- d->maximumTime = time;
- break;
- }
- case EndTrace: {
- QList<int> engineIds;
- while (!stream.atEnd()) {
- int id;
- stream >> id;
- engineIds << id;
- }
- emit traceFinished(time, engineIds);
- d->maximumTime = time;
- d->maximumTime = qMax(time, d->maximumTime);
- break;
- }
- case AnimationFrame: {
- if (!d->updateFeatures(ProfileAnimations))
- break;
- int frameRate, animationCount;
- int threadId;
- stream >> frameRate >> animationCount;
- if (!stream.atEnd())
- stream >> threadId;
- else
- threadId = 0;
-
- emit rangedEvent(Event, MaximumRangeType, AnimationFrame, time, 0, QString(),
- QmlEventLocation(), frameRate, animationCount, threadId,
- 0, 0);
- d->maximumTime = qMax(time, d->maximumTime);
- break;
- }
- case Key:
- case Mouse:
- if (!d->updateFeatures(ProfileInputEvents))
- break;
- int inputType = (subtype == Key ? InputKeyUnknown : InputMouseUnknown);
- if (!stream.atEnd())
- stream >> inputType;
- int a = -1;
- if (!stream.atEnd())
- stream >> a;
- int b = -1;
- if (!stream.atEnd())
- stream >> b;
+ stream >> d->currentEvent;
- emit rangedEvent(Event, MaximumRangeType, subtype, time, 0, QString(),
- QmlEventLocation(), inputType, a, b, 0, 0);
- d->maximumTime = qMax(time, d->maximumTime);
- break;
- }
-
- break;
- }
- case Complete:
+ d->maximumTime = qMax(d->currentEvent.event.timestamp(), d->maximumTime);
+ if (d->currentEvent.type.message == Complete) {
emit complete(d->maximumTime);
setRecordingFromServer(false);
- break;
- case SceneGraphFrame: {
- if (!d->updateFeatures(ProfileSceneGraph))
- break;
-
- int count = 0;
- qint64 params[5];
-
- while (!stream.atEnd()) {
- stream >> params[count++];
- }
- while (count<5)
- params[count++] = 0;
- emit rangedEvent(SceneGraphFrame, MaximumRangeType, subtype,time, 0,
- QString(), QmlEventLocation(), params[0], params[1],
- params[2], params[3], params[4]);
- break;
- }
- case PixmapCacheEvent: {
- if (!d->updateFeatures(ProfilePixmapCache))
- break;
- int width = 0, height = 0, refcount = 0;
- QString pixUrl;
- stream >> pixUrl;
- if (subtype == (int)PixmapReferenceCountChanged || subtype == (int)PixmapCacheCountChanged) {
- stream >> refcount;
- } else if (subtype == (int)PixmapSizeKnown) {
- stream >> width >> height;
- refcount = 1;
- }
- emit rangedEvent(PixmapCacheEvent, MaximumRangeType, subtype, time, 0,
- QString(), QmlEventLocation(pixUrl,0,0), width, height,
- refcount, 0, 0);
- d->maximumTime = qMax(time, d->maximumTime);
- break;
- }
- case MemoryAllocation: {
- if (!d->updateFeatures(ProfileMemory))
- break;
-
- qint64 delta;
- stream >> delta;
- emit rangedEvent(MemoryAllocation, MaximumRangeType, subtype, time, 0,
- QString(), QmlEventLocation(), delta, 0, 0, 0, 0);
- d->maximumTime = qMax(time, d->maximumTime);
- break;
- }
- case RangeStart: {
- if (!d->updateFeatures(featureFromRangeType(static_cast<RangeType>(subtype))))
- break;
- d->rangeStartTimes[subtype].push(time);
- d->inProgressRanges |= (static_cast<qint64>(1) << subtype);
- ++d->rangeCount[subtype];
-
- // read binding type
- if ((RangeType)subtype == Binding) {
- int bindingType = (int)QmlBinding;
- if (!stream.atEnd())
- stream >> bindingType;
- d->bindingTypes.push((BindingType)bindingType);
- }
- break;
- }
- case RangeData: {
- if (!d->updateFeatures(featureFromRangeType(static_cast<RangeType>(subtype))))
- break;
- QString data;
- stream >> data;
-
- int count = d->rangeCount[subtype];
- if (count > 0) {
- while (d->rangeDatas[subtype].count() < count)
- d->rangeDatas[subtype].push(QString());
- d->rangeDatas[subtype][count-1] = data;
- }
- break;
- }
- case RangeLocation: {
- if (!d->updateFeatures(featureFromRangeType(static_cast<RangeType>(subtype))))
- break;
- QString fileName;
- int line;
- int column = -1;
- stream >> fileName >> line;
-
- if (!stream.atEnd())
- stream >> column;
-
- if (d->rangeCount[subtype] > 0)
- d->rangeLocations[subtype].push(QmlEventLocation(fileName, line, column));
- break;
- }
- case RangeEnd: {
- if (!d->updateFeatures(featureFromRangeType(static_cast<RangeType>(subtype))))
- break;
- if (d->rangeCount[subtype] == 0)
- break;
- --d->rangeCount[subtype];
- if (d->inProgressRanges & (static_cast<qint64>(1) << subtype))
- d->inProgressRanges &= ~(static_cast<qint64>(1) << subtype);
-
- d->maximumTime = qMax(time, d->maximumTime);
- QString data = d->rangeDatas[subtype].count() ? d->rangeDatas[subtype].pop() : QString();
- QmlEventLocation location = d->rangeLocations[subtype].count() ? d->rangeLocations[subtype].pop() : QmlEventLocation();
-
- qint64 startTime = d->rangeStartTimes[subtype].pop();
- BindingType bindingType = QmlBinding;
- if ((RangeType)subtype == Binding)
- bindingType = d->bindingTypes.pop();
- if ((RangeType)subtype == Painting)
- bindingType = QPainterEvent;
- emit rangedEvent(MaximumMessage, (RangeType)subtype, bindingType, startTime,
- time - startTime, data, location, 0, 0, 0, 0, 0);
- if (d->rangeCount[subtype] == 0) {
- int count = d->rangeDatas[subtype].count() +
- d->rangeStartTimes[subtype].count() +
- d->rangeLocations[subtype].count();
- if (count != 0)
- qWarning() << "incorrectly nested data";
- }
- break;
- }
- default:
- break;
+ } else if (d->currentEvent.type.message == Event
+ && d->currentEvent.type.detailType == StartTrace) {
+ if (!d->recording)
+ setRecordingFromServer(true);
+ emit traceStarted(d->currentEvent.event.timestamp(),
+ d->currentEvent.event.numbers<QList<int>, qint32>());
+ } else if (d->currentEvent.type.message == Event
+ && d->currentEvent.type.detailType == EndTrace) {
+ emit traceFinished(d->currentEvent.event.timestamp(),
+ d->currentEvent.event.numbers<QList<int>, qint32>());
+ } else if (d->updateFeatures(d->currentEvent.type.feature())) {
+ emit qmlEvent(d->currentEvent.event, d->currentEvent.type);
}
}
diff --git a/src/plugins/qmlprofiler/qmlprofilertraceclient.h b/src/plugins/qmlprofiler/qmlprofilertraceclient.h
index c237b1f621..3864a38081 100644
--- a/src/plugins/qmlprofiler/qmlprofilertraceclient.h
+++ b/src/plugins/qmlprofiler/qmlprofilertraceclient.h
@@ -28,6 +28,7 @@
#include "qmlprofilereventtypes.h"
#include "qmleventlocation.h"
#include "qmlprofiler_global.h"
+#include "qmltypedevent.h"
#include <qmldebug/qmldebugclient.h>
@@ -60,12 +61,7 @@ signals:
void traceFinished(qint64 timestamp, const QList<int> &engineIds);
void traceStarted(qint64 timestamp, const QList<int> &engineIds);
- void rangedEvent(Message, RangeType, int detailType, qint64 startTime, qint64 length,
- const QString &data, const QmlEventLocation &location, qint64 param1,
- qint64 param2, qint64 param3, qint64 param4, qint64 param5);
-
- void debugMessage(qint64 timestamp, QtMsgType type, const QString &text,
- const QmlEventLocation &location);
+ void qmlEvent(const QmlEvent &event, const QmlEventType &type);
void recordingChanged(bool arg);
void recordedFeaturesChanged(quint64 features);
diff --git a/src/plugins/qmlprofiler/qmlprofilertracefile.cpp b/src/plugins/qmlprofiler/qmlprofilertracefile.cpp
index ca15d28eb6..e726448303 100644
--- a/src/plugins/qmlprofiler/qmlprofilertracefile.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertracefile.cpp
@@ -31,6 +31,7 @@
#include <QStringList>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
+#include <QStack>
#include <QDebug>
namespace QmlProfiler {
@@ -181,6 +182,9 @@ bool QmlProfilerFileReader::load(QIODevice *device)
emit error(tr("Error while parsing trace data file: %1").arg(stream.errorString()));
return false;
} else {
+ std::sort(m_events.begin(), m_events.end(), [](const QmlEvent &a, const QmlEvent &b) {
+ return a.timestamp() < b.timestamp();
+ });
emit success();
return true;
}
@@ -370,46 +374,53 @@ void QmlProfilerFileReader::loadEvents(QXmlStreamReader &stream)
}
event.setTimestamp(attributes.value(_("startTime")).toLongLong());
- if (attributes.hasAttribute(_("duration")))
- event.setDuration(attributes.value(_("duration")).toLongLong());
-
- // attributes for special events
- if (attributes.hasAttribute(_("framerate")))
- event.setNumber<qint32>(0, attributes.value(_("framerate")).toInt());
- if (attributes.hasAttribute(_("animationcount")))
- event.setNumber<qint32>(1, attributes.value(_("animationcount")).toInt());
- if (attributes.hasAttribute(_("thread")))
- event.setNumber<qint32>(2, attributes.value(_("thread")).toInt());
- if (attributes.hasAttribute(_("width")))
- event.setNumber<qint32>(0, attributes.value(_("width")).toInt());
- if (attributes.hasAttribute(_("height")))
- event.setNumber<qint32>(1, attributes.value(_("height")).toInt());
- if (attributes.hasAttribute(_("refCount")))
- event.setNumber<qint32>(2, attributes.value(_("refCount")).toInt());
- if (attributes.hasAttribute(_("amount")))
- event.setNumber<qint64>(0, attributes.value(_("amount")).toLongLong());
- if (attributes.hasAttribute(_("timing1")))
- event.setNumber<qint64>(0, attributes.value(_("timing1")).toLongLong());
- if (attributes.hasAttribute(_("timing2")))
- event.setNumber<qint64>(1, attributes.value(_("timing2")).toLongLong());
- if (attributes.hasAttribute(_("timing3")))
- event.setNumber<qint64>(2, attributes.value(_("timing3")).toLongLong());
- if (attributes.hasAttribute(_("timing4")))
- event.setNumber<qint64>(3, attributes.value(_("timing4")).toLongLong());
- if (attributes.hasAttribute(_("timing5")))
- event.setNumber<qint64>(4, attributes.value(_("timing5")).toLongLong());
- if (attributes.hasAttribute(_("type")))
- event.setNumber<qint32>(0, attributes.value(_("type")).toInt());
- if (attributes.hasAttribute(_("data1")))
- event.setNumber<qint32>(1, attributes.value(_("data1")).toInt());
- if (attributes.hasAttribute(_("data2")))
- event.setNumber<qint32>(2, attributes.value(_("data2")).toInt());
- if (attributes.hasAttribute(_("text")))
- event.setString(attributes.value(_("text")).toString());
-
event.setTypeIndex(attributes.value(_("eventIndex")).toInt());
- m_events.append(event);
+ if (attributes.hasAttribute(_("duration"))) {
+ event.setRangeStage(RangeStart);
+ m_events.append(event);
+ QmlEvent rangeEnd(event);
+ rangeEnd.setRangeStage(RangeEnd);
+ rangeEnd.setTimestamp(event.timestamp()
+ + attributes.value(_("duration")).toLongLong());
+ m_events.append(rangeEnd);
+ } else {
+ // attributes for special events
+ if (attributes.hasAttribute(_("framerate")))
+ event.setNumber<qint32>(0, attributes.value(_("framerate")).toInt());
+ if (attributes.hasAttribute(_("animationcount")))
+ event.setNumber<qint32>(1, attributes.value(_("animationcount")).toInt());
+ if (attributes.hasAttribute(_("thread")))
+ event.setNumber<qint32>(2, attributes.value(_("thread")).toInt());
+ if (attributes.hasAttribute(_("width")))
+ event.setNumber<qint32>(0, attributes.value(_("width")).toInt());
+ if (attributes.hasAttribute(_("height")))
+ event.setNumber<qint32>(1, attributes.value(_("height")).toInt());
+ if (attributes.hasAttribute(_("refCount")))
+ event.setNumber<qint32>(2, attributes.value(_("refCount")).toInt());
+ if (attributes.hasAttribute(_("amount")))
+ event.setNumber<qint64>(0, attributes.value(_("amount")).toLongLong());
+ if (attributes.hasAttribute(_("timing1")))
+ event.setNumber<qint64>(0, attributes.value(_("timing1")).toLongLong());
+ if (attributes.hasAttribute(_("timing2")))
+ event.setNumber<qint64>(1, attributes.value(_("timing2")).toLongLong());
+ if (attributes.hasAttribute(_("timing3")))
+ event.setNumber<qint64>(2, attributes.value(_("timing3")).toLongLong());
+ if (attributes.hasAttribute(_("timing4")))
+ event.setNumber<qint64>(3, attributes.value(_("timing4")).toLongLong());
+ if (attributes.hasAttribute(_("timing5")))
+ event.setNumber<qint64>(4, attributes.value(_("timing5")).toLongLong());
+ if (attributes.hasAttribute(_("type")))
+ event.setNumber<qint32>(0, attributes.value(_("type")).toInt());
+ if (attributes.hasAttribute(_("data1")))
+ event.setNumber<qint32>(1, attributes.value(_("data1")).toInt());
+ if (attributes.hasAttribute(_("data2")))
+ event.setNumber<qint32>(2, attributes.value(_("data2")).toInt());
+ if (attributes.hasAttribute(_("text")))
+ event.setString(attributes.value(_("text")).toString());
+
+ m_events.append(event);
+ }
}
break;
}
@@ -584,19 +595,29 @@ void QmlProfilerFileWriter::save(QIODevice *device)
stream.writeStartElement(_("profilerDataModel"));
+ QStack<QmlEvent> stack;
for (int rangeIndex = 0; rangeIndex < m_events.size(); ++rangeIndex) {
if (isCanceled())
return;
const QmlEvent &event = m_events[rangeIndex];
+ const QmlEventType &type = m_eventTypes[event.typeIndex()];
+ if (type.rangeType != MaximumRangeType && event.rangeStage() == RangeStart) {
+ stack.push(event);
+ continue;
+ }
stream.writeStartElement(_("range"));
- stream.writeAttribute(_("startTime"), QString::number(event.timestamp()));
- if (event.duration() > 0) // no need to store duration of instantaneous events
- stream.writeAttribute(_("duration"), QString::number(event.duration()));
- stream.writeAttribute(_("eventIndex"), QString::number(event.typeIndex()));
+ if (type.rangeType != MaximumRangeType && event.rangeStage() == RangeEnd) {
+ QmlEvent start = stack.pop();
+ stream.writeAttribute(_("startTime"), QString::number(start.timestamp()));
+ stream.writeAttribute(_("duration"),
+ QString::number(event.timestamp() - start.timestamp()));
+ } else {
+ stream.writeAttribute(_("startTime"), QString::number(event.timestamp()));
+ }
- const QmlEventType &type = m_eventTypes[event.typeIndex()];
+ stream.writeAttribute(_("eventIndex"), QString::number(event.typeIndex()));
if (type.message == Event) {
if (type.detailType == AnimationFrame) {
diff --git a/src/plugins/qmlprofiler/qmlprofilerviewmanager.cpp b/src/plugins/qmlprofiler/qmlprofilerviewmanager.cpp
index cba27c6213..a9535db655 100644
--- a/src/plugins/qmlprofiler/qmlprofilerviewmanager.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerviewmanager.cpp
@@ -133,17 +133,12 @@ qint64 QmlProfilerViewManager::selectionEnd() const
bool QmlProfilerViewManager::isEventsRestrictedToRange() const
{
- foreach (QmlProfilerEventsView *view, d->eventsViews) {
- if (view->isRestrictedToRange())
- return true;
- }
- return false;
+ return d->profilerModelManager->isRestrictedToRange();
}
void QmlProfilerViewManager::restrictEventsToRange(qint64 rangeStart, qint64 rangeEnd)
{
- foreach (QmlProfilerEventsView *view, d->eventsViews)
- view->restrictToRange(rangeStart, rangeEnd);
+ d->profilerModelManager->restrictToRange(rangeStart, rangeEnd);
}
void QmlProfilerViewManager::raiseTimeline()