forked from qt-creator/qt-creator
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: Alex Blasche <alexander.blasche@theqtcompany.com> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
@@ -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,64 +93,66 @@ 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) {
|
||||
if (!m_acceptedTypes.contains(type.rangeType))
|
||||
return;
|
||||
|
||||
if (m_stackBottom.children.isEmpty())
|
||||
beginResetModel();
|
||||
clear();
|
||||
endResetModel();
|
||||
return;
|
||||
} else if (m_modelManager->state() != QmlProfilerModelManager::ProcessingData &&
|
||||
m_modelManager->state() != QmlProfilerModelManager::Done) {
|
||||
return;
|
||||
|
||||
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();
|
||||
clear();
|
||||
|
||||
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;
|
||||
|
||||
if (checkRanges) {
|
||||
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);
|
||||
}
|
||||
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();
|
||||
|
||||
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)
|
||||
{
|
||||
switch (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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user