summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/plugins/qmlprofiler/flamegraphmodel.cpp101
-rw-r--r--src/plugins/qmlprofiler/flamegraphmodel.h12
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp355
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.h54
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp8
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerstatisticsview.h2
6 files changed, 247 insertions, 285 deletions
diff --git a/src/plugins/qmlprofiler/flamegraphmodel.cpp b/src/plugins/qmlprofiler/flamegraphmodel.cpp
index d28cec914e..2a2055a0df 100644
--- a/src/plugins/qmlprofiler/flamegraphmodel.cpp
+++ b/src/plugins/qmlprofiler/flamegraphmodel.cpp
@@ -33,7 +33,6 @@
#include <QVector>
#include <QString>
-#include <QStack>
#include <QQueue>
#include <QSet>
@@ -44,8 +43,10 @@ FlameGraphModel::FlameGraphModel(QmlProfilerModelManager *modelManager,
QObject *parent) : QAbstractItemModel(parent)
{
m_modelManager = modelManager;
- connect(modelManager->qmlModel(), &QmlProfilerDataModel::changed,
- this, [this](){loadData();});
+ m_callStack.append(QmlEvent());
+ m_stackTop = &m_stackBottom;
+ connect(modelManager, &QmlProfilerModelManager::stateChanged,
+ this, &FlameGraphModel::onModelManagerStateChanged);
connect(modelManager->notesModel(), &Timeline::TimelineNotesModel::changed,
this, [this](int typeId, int, int){loadNotes(typeId, true);});
m_modelId = modelManager->registerModelProxy();
@@ -61,8 +62,13 @@ FlameGraphModel::FlameGraphModel(QmlProfilerModelManager *modelManager,
void FlameGraphModel::clear()
{
+ beginResetModel();
m_stackBottom = FlameGraphData();
+ m_callStack.clear();
+ m_callStack.append(QmlEvent());
+ m_stackTop = &m_stackBottom;
m_typeIdsWithNotes.clear();
+ endResetModel();
}
void FlameGraphModel::loadNotes(int typeIndex, bool emitSignal)
@@ -87,62 +93,64 @@ void FlameGraphModel::loadNotes(int typeIndex, bool emitSignal)
emit dataChanged(QModelIndex(), QModelIndex(), QVector<int>() << NoteRole);
}
-void FlameGraphModel::loadData(qint64 rangeStart, qint64 rangeEnd)
+void FlameGraphModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
{
- const bool checkRanges = (rangeStart != -1) && (rangeEnd != -1);
- if (m_modelManager->state() == QmlProfilerModelManager::ClearingData) {
- beginResetModel();
- clear();
- endResetModel();
- return;
- } else if (m_modelManager->state() != QmlProfilerModelManager::ProcessingData &&
- m_modelManager->state() != QmlProfilerModelManager::Done) {
+ if (!m_acceptedTypes.contains(type.rangeType))
return;
+
+ if (m_stackBottom.children.isEmpty())
+ beginResetModel();
+
+ const QmlEvent *potentialParent = &(m_callStack.top());
+ while (potentialParent->isValid() &&
+ potentialParent->timestamp() + potentialParent->duration() <= event.timestamp()) {
+ m_callStack.pop();
+ m_stackTop = m_stackTop->parent;
+ potentialParent = &(m_callStack.top());
}
- beginResetModel();
+ m_callStack.push(event);
+ m_stackTop = pushChild(m_stackTop, event);
+}
+
+void FlameGraphModel::finalize()
+{
+ foreach (FlameGraphData *child, m_stackBottom.children)
+ m_stackBottom.duration += child->duration;
+
+ loadNotes(-1, false);
+ endResetModel();
+}
+
+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();
- // used by binding loop detection
- QStack<const QmlEvent *> callStack;
- callStack.append(0);
- FlameGraphData *stackTop = &m_stackBottom;
-
for (int i = 0; i < eventList.size(); ++i) {
- const QmlEvent *event = &eventList[i];
- int typeIndex = event->typeIndex();
- const QmlEventType *type = &typesList[typeIndex];
-
- if (!m_acceptedTypes.contains(type->rangeType))
- continue;
+ const QmlEvent &event = eventList[i];
if (checkRanges) {
- if ((event->timestamp() + event->duration() < rangeStart)
- || (event->timestamp() > rangeEnd))
+ if ((event.timestamp() + event.duration() < rangeStart)
+ || (event.timestamp() > rangeEnd))
continue;
}
- const QmlEvent *potentialParent = callStack.top();
- while (potentialParent &&
- potentialParent->timestamp() + potentialParent->duration() <= event->timestamp()) {
- callStack.pop();
- stackTop = stackTop->parent;
- potentialParent = callStack.top();
- }
-
- callStack.push(event);
- stackTop = pushChild(stackTop, event);
+ loadEvent(event, typesList[event.typeIndex()]);
}
- foreach (FlameGraphData *child, m_stackBottom.children)
- m_stackBottom.duration += child->duration;
-
- loadNotes(-1, false);
-
- endResetModel();
+ finalize();
}
static QString nameForType(RangeType typeNumber)
@@ -210,18 +218,17 @@ FlameGraphData::~FlameGraphData()
qDeleteAll(children);
}
-FlameGraphData *FlameGraphModel::pushChild(
- FlameGraphData *parent, const QmlEvent *data)
+FlameGraphData *FlameGraphModel::pushChild(FlameGraphData *parent, const QmlEvent &data)
{
foreach (FlameGraphData *child, parent->children) {
- if (child->typeIndex == data->typeIndex()) {
+ if (child->typeIndex == data.typeIndex()) {
++child->calls;
- child->duration += data->duration();
+ child->duration += data.duration();
return child;
}
}
- FlameGraphData *child = new FlameGraphData(parent, data->typeIndex(), data->duration());
+ FlameGraphData *child = new FlameGraphData(parent, data.typeIndex(), data.duration());
parent->children.append(child);
return child;
}
diff --git a/src/plugins/qmlprofiler/flamegraphmodel.h b/src/plugins/qmlprofiler/flamegraphmodel.h
index 096a18add3..547d3bc890 100644
--- a/src/plugins/qmlprofiler/flamegraphmodel.h
+++ b/src/plugins/qmlprofiler/flamegraphmodel.h
@@ -32,6 +32,7 @@
#include <QSet>
#include <QVector>
+#include <QStack>
#include <QAbstractItemModel>
namespace QmlProfiler {
@@ -81,8 +82,12 @@ public:
QHash<int, QByteArray> roleNames() const override;
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();
private:
friend class FlameGraphRelativesModel;
@@ -90,11 +95,14 @@ private:
friend class FlameGraphChildrenModel;
QVariant lookup(const FlameGraphData &data, int role) const;
- void clear();
- FlameGraphData *pushChild(FlameGraphData *parent, const QmlEvent *data);
+ FlameGraphData *pushChild(FlameGraphData *parent, const QmlEvent &data);
int m_selectedTypeIndex;
+
+ // used by binding loop detection
+ QStack<QmlEvent> m_callStack;
FlameGraphData m_stackBottom;
+ FlameGraphData *m_stackTop;
int m_modelId;
QmlProfilerModelManager *m_modelManager;
diff --git a/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp b/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp
index 5ee49e123d..ae4d59961c 100644
--- a/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp
@@ -35,6 +35,7 @@
#include <QString>
#include <QStack>
#include <QSet>
+#include <QPointer>
namespace QmlProfiler {
@@ -42,6 +43,8 @@ class QmlProfilerStatisticsModel::QmlProfilerStatisticsModelPrivate
{
public:
QHash<int, QmlProfilerStatisticsModel::QmlEventStats> data;
+ QPointer<QmlProfilerStatisticsRelativesModel> childrenModel;
+ QPointer<QmlProfilerStatisticsRelativesModel> parentsModel;
QmlProfilerModelManager *modelManager;
@@ -50,6 +53,11 @@ public:
QList<RangeType> acceptedTypes;
QSet<int> eventsInBindingLoop;
QHash<int, QString> notes;
+
+ QStack<QmlEvent> callStack;
+ qint64 qmlTime = 0;
+ qint64 lastEndTime = 0;
+ QHash <int, QVector<qint64> > durations;
};
QmlProfilerStatisticsModel::QmlProfilerStatisticsModel(QmlProfilerModelManager *modelManager,
@@ -57,7 +65,8 @@ QmlProfilerStatisticsModel::QmlProfilerStatisticsModel(QmlProfilerModelManager *
QObject(parent), d(new QmlProfilerStatisticsModelPrivate)
{
d->modelManager = modelManager;
- connect(modelManager->qmlModel(), &QmlProfilerDataModel::changed,
+ d->callStack.push(QmlEvent());
+ connect(modelManager, &QmlProfilerModelManager::stateChanged,
this, &QmlProfilerStatisticsModel::dataChanged);
connect(modelManager->notesModel(), &Timeline::TimelineNotesModel::changed,
this, &QmlProfilerStatisticsModel::notesChanged);
@@ -86,11 +95,6 @@ void QmlProfilerStatisticsModel::setEventTypeAccepted(RangeType type, bool accep
d->acceptedTypes.removeOne(type);
}
-bool QmlProfilerStatisticsModel::eventTypeAccepted(RangeType type) const
-{
- return d->acceptedTypes.contains(type);
-}
-
const QHash<int, QmlProfilerStatisticsModel::QmlEventStats> &QmlProfilerStatisticsModel::getData() const
{
return d->data;
@@ -111,6 +115,15 @@ void QmlProfilerStatisticsModel::clear()
d->data.clear();
d->eventsInBindingLoop.clear();
d->notes.clear();
+ d->callStack.clear();
+ d->callStack.push(QmlEvent());
+ d->qmlTime = 0;
+ d->lastEndTime = 0;
+ d->durations.clear();
+ if (!d->childrenModel.isNull())
+ d->childrenModel->clear();
+ if (!d->parentsModel.isNull())
+ d->parentsModel->clear();
}
void QmlProfilerStatisticsModel::limitToRange(qint64 rangeStart, qint64 rangeEnd)
@@ -119,6 +132,15 @@ void QmlProfilerStatisticsModel::limitToRange(qint64 rangeStart, qint64 rangeEnd
loadData(rangeStart, rangeEnd);
}
+void QmlProfilerStatisticsModel::setRelativesModel(QmlProfilerStatisticsRelativesModel *relative,
+ QmlProfilerStatisticsRelation relation)
+{
+ if (relation == QmlProfilerStatisticsParents)
+ d->parentsModel = relative;
+ else
+ d->childrenModel = relative;
+}
+
void QmlProfilerStatisticsModel::dataChanged()
{
if (d->modelManager->state() == QmlProfilerModelManager::ProcessingData)
@@ -159,98 +181,103 @@ void QmlProfilerStatisticsModel::notesChanged(int typeIndex)
emit notesAvailable(typeIndex);
}
-const QSet<int> &QmlProfilerStatisticsModel::eventsInBindingLoop() const
-{
- return d->eventsInBindingLoop;
-}
-
void QmlProfilerStatisticsModel::loadData(qint64 rangeStart, qint64 rangeEnd)
{
clear();
- qint64 qmlTime = 0;
- qint64 lastEndTime = 0;
- QHash <int, QVector<qint64> > durations;
-
const bool checkRanges = (rangeStart != -1) && (rangeEnd != -1);
const QVector<QmlEvent> &eventList = d->modelManager->qmlModel()->events();
const QVector<QmlEventType> &typesList = d->modelManager->qmlModel()->eventTypes();
- // used by binding loop detection
- QStack<const QmlEvent*> callStack;
- callStack.push(0); // artificial root
-
for (int i = 0; i < eventList.size(); ++i) {
- const QmlEvent *event = &eventList[i];
- const QmlEventType *type = &typesList[event->typeIndex()];
-
- if (!d->acceptedTypes.contains(type->rangeType))
- continue;
+ const QmlEvent &event = eventList[i];
+ const QmlEventType &type = typesList[event.typeIndex()];
if (checkRanges) {
- if ((event->timestamp() + event->duration() < rangeStart)
- || (event->timestamp() > rangeEnd))
+ if ((event.timestamp() + event.duration() < rangeStart)
+ || (event.timestamp() > rangeEnd))
continue;
}
- // update stats
- QmlEventStats *stats = &d->data[event->typeIndex()];
+ loadEvent(event, type);
+ }
- 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++;
+ finalize();
+ if (checkRanges)
+ notesChanged(-1); // Reload notes
+}
- // for median computing
- durations[event->typeIndex()].append(event->duration());
+void QmlProfilerStatisticsModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
+{
+ if (!d->acceptedTypes.contains(type.rangeType))
+ return;
- // qml time computation
- if (event->timestamp() > lastEndTime) { // assume parent event if starts before last end
- qmlTime += event->duration();
- lastEndTime = event->timestamp() + event->duration();
- }
+ // update stats
+ QmlEventStats *stats = &d->data[event.typeIndex()];
- //
- // binding loop detection
- //
- const QmlEvent *potentialParent = callStack.top();
- while (potentialParent && !(potentialParent->timestamp() + potentialParent->duration() >
- event->timestamp())) {
- callStack.pop();
- potentialParent = callStack.top();
- }
+ 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++;
- // check whether event is already in stack
- for (int ii = 1; ii < callStack.size(); ++ii) {
- if (callStack.at(ii)->typeIndex() == event->typeIndex()) {
- d->eventsInBindingLoop.insert(event->typeIndex());
- break;
- }
- }
+ // for median computing
+ d->durations[event.typeIndex()].append(event.duration());
- if (callStack.count() > 1)
- d->data[callStack.top()->typeIndex()].durationSelf -= event->duration();
- callStack.push(event);
+ // 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();
}
+ //
+ // 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());
+ }
+
+ // 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;
+ }
+ }
+
+ 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())
+ d->parentsModel->loadEvent(event);
+}
+
+
+void QmlProfilerStatisticsModel::finalize()
+{
// post-process: calc mean time, median time, percentoftime
for (QHash<int, QmlEventStats>::iterator it = d->data.begin(); it != d->data.end(); ++it) {
QmlEventStats* stats = &it.value();
if (stats->calls > 0)
stats->timePerCall = stats->duration / (double)stats->calls;
- QVector<qint64> eventDurations = durations[it.key()];
+ QVector<qint64> eventDurations = d->durations[it.key()];
if (!eventDurations.isEmpty()) {
Utils::sort(eventDurations);
stats->medianTime = eventDurations.at(eventDurations.count()/2);
}
- stats->percentOfTime = stats->duration * 100.0 / qmlTime;
- stats->percentSelf = stats->durationSelf * 100.0 / qmlTime;
+ stats->percentOfTime = stats->duration * 100.0 / d->qmlTime;
+ stats->percentSelf = stats->durationSelf * 100.0 / d->qmlTime;
}
// set binding loop flag
@@ -260,13 +287,17 @@ void QmlProfilerStatisticsModel::loadData(qint64 rangeStart, qint64 rangeEnd)
// insert root event
QmlEventStats rootEvent;
rootEvent.duration = rootEvent.minTime = rootEvent.maxTime = rootEvent.timePerCall
- = rootEvent.medianTime = qmlTime + 1;
+ = rootEvent.medianTime = d->qmlTime + 1;
rootEvent.durationSelf = 1;
rootEvent.calls = 1;
rootEvent.percentOfTime = 100.0;
rootEvent.percentSelf = 1.0 / rootEvent.duration;
d->data.insert(-1, rootEvent);
+ if (!d->childrenModel.isNull())
+ d->childrenModel->finalize(d->eventsInBindingLoop);
+ if (!d->parentsModel.isNull())
+ d->parentsModel->finalize(d->eventsInBindingLoop);
emit dataAvailable();
}
@@ -278,18 +309,21 @@ int QmlProfilerStatisticsModel::count() const
QmlProfilerStatisticsRelativesModel::QmlProfilerStatisticsRelativesModel(
QmlProfilerModelManager *modelManager, QmlProfilerStatisticsModel *statisticsModel,
- QObject *parent) : QObject(parent)
+ QmlProfilerStatisticsRelation relation, QObject *parent) :
+ QObject(parent), m_relation(relation)
{
+ m_endtimesPerLevel[0] = 0;
+
QTC_CHECK(modelManager);
m_modelManager = modelManager;
QTC_CHECK(statisticsModel);
- m_statisticsModel = statisticsModel;
+ statisticsModel->setRelativesModel(this, relation);
// Load the child models whenever the parent model is done to get the filtering for JS/QML
// right.
- connect(m_statisticsModel, &QmlProfilerStatisticsModel::dataAvailable,
- this, &QmlProfilerStatisticsRelativesModel::dataChanged);
+ connect(statisticsModel, &QmlProfilerStatisticsModel::dataAvailable,
+ this, &QmlProfilerStatisticsRelativesModel::dataAvailable);
}
const QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesMap &
@@ -309,146 +343,69 @@ const QVector<QmlEventType> &QmlProfilerStatisticsRelativesModel::getTypes() con
return m_modelManager->qmlModel()->eventTypes();
}
-int QmlProfilerStatisticsRelativesModel::count() const
-{
- return m_data.count();
-}
-
-void QmlProfilerStatisticsRelativesModel::clear()
+void QmlProfilerStatisticsRelativesModel::loadEvent(const QmlEvent &event)
{
- m_data.clear();
-}
-
-void QmlProfilerStatisticsRelativesModel::dataChanged()
-{
- loadData();
+ // 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--;
+ }
+ 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);
+ }
- emit dataAvailable();
+ // now lastparent is the new type
+ m_lastParent[m_level] = event.typeIndex();
}
-QmlProfilerStatisticsParentsModel::QmlProfilerStatisticsParentsModel(
- QmlProfilerModelManager *modelManager, QmlProfilerStatisticsModel *statisticsModel,
- QObject *parent) :
- QmlProfilerStatisticsRelativesModel(modelManager, statisticsModel, parent)
-{}
-
-void QmlProfilerStatisticsParentsModel::loadData()
+void QmlProfilerStatisticsRelativesModel::finalize(const QSet<int> &eventsInBindingLoop)
{
- clear();
- QmlProfilerDataModel *simpleModel = m_modelManager->qmlModel();
- if (simpleModel->isEmpty())
- return;
-
- // for level computation
- QHash<int, qint64> endtimesPerLevel;
- int level = Constants::QML_MIN_LEVEL;
- endtimesPerLevel[0] = 0;
-
- const QSet<int> &eventsInBindingLoop = m_statisticsModel->eventsInBindingLoop();
-
- // compute parent-child relationship and call count
- QHash<int, int> lastParent;
- const QVector<QmlEvent> eventList = simpleModel->events();
- const QVector<QmlEventType> typesList = simpleModel->eventTypes();
- foreach (const QmlEvent &event, eventList) {
- // whitelist
- if (!m_statisticsModel->eventTypeAccepted(typesList[event.typeIndex()].rangeType))
- continue;
-
- // level computation
- if (endtimesPerLevel[level] > event.timestamp()) {
- level++;
- } else {
- while (level > Constants::QML_MIN_LEVEL &&
- endtimesPerLevel[level-1] <= event.timestamp())
- level--;
- }
- endtimesPerLevel[level] = event.timestamp() + event.duration();
-
- int parentTypeIndex = -1;
- if (level > Constants::QML_MIN_LEVEL && lastParent.contains(level-1))
- parentTypeIndex = lastParent[level-1];
-
- QmlStatisticsRelativesMap &relativesMap = m_data[event.typeIndex()];
- QmlStatisticsRelativesMap::Iterator it = relativesMap.find(parentTypeIndex);
- if (it != relativesMap.end()) {
- it.value().calls++;
- it.value().duration += event.duration();
- } else {
- QmlStatisticsRelativesData parent = {
- event.duration(),
- 1,
- eventsInBindingLoop.contains(parentTypeIndex)
- };
- relativesMap.insert(parentTypeIndex, parent);
+ for (auto map = m_data.begin(), mapEnd = m_data.end(); map != mapEnd; ++map) {
+ auto itemEnd = map->end();
+ foreach (int typeIndex, eventsInBindingLoop) {
+ auto item = map->find(typeIndex);
+ if (item != itemEnd)
+ item->isBindingLoop = true;
}
-
- // now lastparent is the new type
- lastParent[level] = event.typeIndex();
}
}
-QmlProfilerStatisticsChildrenModel::QmlProfilerStatisticsChildrenModel(
- QmlProfilerModelManager *modelManager, QmlProfilerStatisticsModel *statisticsModel,
- QObject *parent) :
- QmlProfilerStatisticsRelativesModel(modelManager, statisticsModel, parent)
-{}
-
-void QmlProfilerStatisticsChildrenModel::loadData()
+int QmlProfilerStatisticsRelativesModel::count() const
{
- clear();
- QmlProfilerDataModel *simpleModel = m_modelManager->qmlModel();
- if (simpleModel->isEmpty())
- return;
-
- // for level computation
- QHash<int, qint64> endtimesPerLevel;
- int level = Constants::QML_MIN_LEVEL;
- endtimesPerLevel[0] = 0;
-
- const QSet<int> &eventsInBindingLoop = m_statisticsModel->eventsInBindingLoop();
-
- // compute parent-child relationship and call count
- QHash<int, int> lastParent;
- const QVector<QmlEvent> &eventList = simpleModel->events();
- const QVector<QmlEventType> &typesList = simpleModel->eventTypes();
- foreach (const QmlEvent &event, eventList) {
- // whitelist
- if (!m_statisticsModel->eventTypeAccepted(typesList[event.typeIndex()].rangeType))
- continue;
-
- // level computation
- if (endtimesPerLevel[level] > event.timestamp()) {
- level++;
- } else {
- while (level > Constants::QML_MIN_LEVEL &&
- endtimesPerLevel[level-1] <= event.timestamp())
- level--;
- }
- endtimesPerLevel[level] = event.timestamp() + event.duration();
-
- int parentId = -1;
-
- if (level > Constants::QML_MIN_LEVEL && lastParent.contains(level-1))
- parentId = lastParent[level-1];
-
- QmlStatisticsRelativesMap &relativesMap = m_data[parentId];
- QmlStatisticsRelativesMap::Iterator it = relativesMap.find(event.typeIndex());
- if (it != relativesMap.end()) {
- it.value().calls++;
- it.value().duration += event.duration();
- } else {
- QmlStatisticsRelativesData child = {
- event.duration(),
- 1,
- eventsInBindingLoop.contains(parentId)
- };
- relativesMap.insert(event.typeIndex(), child);
- }
-
- // now lastparent is the new type
- lastParent[level] = event.typeIndex();
- }
+ return m_data.count();
}
+void QmlProfilerStatisticsRelativesModel::clear()
+{
+ m_data.clear();
+ m_endtimesPerLevel.clear();
+ m_level = Constants::QML_MIN_LEVEL;
+ m_endtimesPerLevel[0] = 0;
+ m_lastParent.clear();
}
+
+} // namespace QmlProfiler
diff --git a/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.h b/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.h
index 5068e0fe2c..6c28116ad1 100644
--- a/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.h
+++ b/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.h
@@ -37,6 +37,12 @@
namespace QmlProfiler {
class QmlProfilerModelManager;
+class QmlProfilerStatisticsRelativesModel;
+
+enum QmlProfilerStatisticsRelation {
+ QmlProfilerStatisticsChilden,
+ QmlProfilerStatisticsParents
+};
class QmlProfilerStatisticsModel : public QObject
{
@@ -63,7 +69,6 @@ public:
~QmlProfilerStatisticsModel();
void setEventTypeAccepted(RangeType type, bool accepted);
- bool eventTypeAccepted(RangeType) const;
const QHash<int, QmlEventStats> &getData() const;
const QVector<QmlEventType> &getTypes() const;
@@ -73,6 +78,8 @@ public:
void clear();
void limitToRange(qint64 rangeStart, qint64 rangeEnd);
+ void setRelativesModel(QmlProfilerStatisticsRelativesModel *childModel,
+ QmlProfilerStatisticsRelation relation);
signals:
void dataAvailable();
@@ -80,7 +87,8 @@ signals:
private:
void loadData(qint64 rangeStart = -1, qint64 rangeEnd = -1);
- const QSet<int> &eventsInBindingLoop() const;
+ void loadEvent(const QmlEvent &event, const QmlEventType &type);
+ void finalize();
private slots:
void dataChanged();
@@ -89,15 +97,13 @@ private slots:
private:
class QmlProfilerStatisticsModelPrivate;
QmlProfilerStatisticsModelPrivate *d;
-
- friend class QmlProfilerStatisticsParentsModel;
- friend class QmlProfilerStatisticsChildrenModel;
};
class QmlProfilerStatisticsRelativesModel : public QObject
{
Q_OBJECT
public:
+
struct QmlStatisticsRelativesData {
qint64 duration;
qint64 calls;
@@ -107,6 +113,7 @@ public:
QmlProfilerStatisticsRelativesModel(QmlProfilerModelManager *modelManager,
QmlProfilerStatisticsModel *statisticsModel,
+ QmlProfilerStatisticsRelation relation,
QObject *parent = 0);
int count() const;
@@ -115,42 +122,23 @@ public:
const QmlStatisticsRelativesMap &getData(int typeId) const;
const QVector<QmlEventType> &getTypes() const;
-protected:
- virtual void loadData() = 0;
+ void loadEvent(const QmlEvent &event);
+ void finalize(const QSet<int> &eventsInBindingLoop);
signals:
void dataAvailable();
-protected slots:
- void dataChanged();
-
protected:
QHash <int, QmlStatisticsRelativesMap> m_data;
QmlProfilerModelManager *m_modelManager;
- QmlProfilerStatisticsModel *m_statisticsModel;
-};
-
-class QmlProfilerStatisticsParentsModel : public QmlProfilerStatisticsRelativesModel
-{
- Q_OBJECT
-public:
- QmlProfilerStatisticsParentsModel(QmlProfilerModelManager *modelManager,
- QmlProfilerStatisticsModel *statisticsModel,
- QObject *parent = 0);
-protected:
- virtual void loadData();
-};
-class QmlProfilerStatisticsChildrenModel : public QmlProfilerStatisticsRelativesModel
-{
- Q_OBJECT
-public:
- QmlProfilerStatisticsChildrenModel(QmlProfilerModelManager *modelManager,
- QmlProfilerStatisticsModel *statisticsModel,
- QObject *parent = 0);
+ // for level computation
+ QHash<int, qint64> m_endtimesPerLevel;
+ int m_level = Constants::QML_MIN_LEVEL;
-protected:
- virtual void loadData();
+ // compute parent-child relationship and call count
+ QHash<int, int> m_lastParent;
+ const QmlProfilerStatisticsRelation m_relation;
};
-}
+} // namespace QmlProfiler
diff --git a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp
index 46574cde7b..579cafc0c3 100644
--- a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp
@@ -191,10 +191,12 @@ QmlProfilerStatisticsView::QmlProfilerStatisticsView(QWidget *parent,
this, &QmlProfilerStatisticsView::typeSelected);
d->m_eventChildren = new QmlProfilerStatisticsRelativesView(
- new QmlProfilerStatisticsChildrenModel(profilerModelManager, d->model, this),
+ new QmlProfilerStatisticsRelativesModel(profilerModelManager, d->model,
+ QmlProfilerStatisticsChilden, this),
this);
d->m_eventParents = new QmlProfilerStatisticsRelativesView(
- new QmlProfilerStatisticsParentsModel(profilerModelManager, d->model, this),
+ new QmlProfilerStatisticsRelativesModel(profilerModelManager, d->model,
+ QmlProfilerStatisticsParents, this),
this);
connect(d->m_eventTree, &QmlProfilerStatisticsMainView::typeSelected,
d->m_eventChildren, &QmlProfilerStatisticsRelativesView::displayType);
@@ -935,7 +937,7 @@ void QmlProfilerStatisticsRelativesView::clear()
void QmlProfilerStatisticsRelativesView::updateHeader()
{
- bool calleesView = qobject_cast<QmlProfilerStatisticsChildrenModel *>(d->model) != 0;
+ bool calleesView = qobject_cast<QmlProfilerStatisticsRelativesModel *>(d->model) != 0;
if (treeModel()) {
treeModel()->setColumnCount(5);
diff --git a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.h b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.h
index 891b23db5a..0bde5adbec 100644
--- a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.h
+++ b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.h
@@ -164,7 +164,7 @@ public slots:
void clear();
private:
- void rebuildTree(const QmlProfilerStatisticsParentsModel::QmlStatisticsRelativesMap &map);
+ void rebuildTree(const QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesMap &map);
void updateHeader();
QStandardItemModel *treeModel();