Commit dd87df7e authored by Ulf Hermann's avatar Ulf Hermann

QmlProfiler: Load data event by event in aggregated models

This paves the way for driving the event loading from the model
manager. Also, unify the loading and eliminate the two different
classes for the children models.

Change-Id: Ic89e757963292d75b3b6fd7d6012f09194dff5a9
Reviewed-by: default avatarAlex Blasche <alexander.blasche@theqtcompany.com>
Reviewed-by: Ulf Hermann's avatarUlf Hermann <ulf.hermann@qt.io>
parent bc18faff
......@@ -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;
}
......
......@@ -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;
......
......@@ -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
......@@ -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);
......
......@@ -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();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment