Commit fbb45e5a authored by Ulf Hermann's avatar Ulf Hermann

QmlProfiler: Keep Compiling events separate in flame graph

The QML compiler can run asynchronously and produce ranges that don't
match up with other QML/JS ranges. The flame graph model assumes that
all ranges are perfectly nested, and produces incorrect data if they
aren't. The compile ranges are perfectly nested among themselves, and
the other QML/JS ranges are also perfectly nested among themselves, so
we can fix this by keeping separate stacks for them.

Change-Id: If4ea251c6a2e74bd04e142cf184937600ea31a87
Reviewed-by: Kai Koehne's avatarKai Koehne <kai.koehne@qt.io>
parent 0eb1301b
......@@ -44,7 +44,9 @@ FlameGraphModel::FlameGraphModel(QmlProfilerModelManager *modelManager,
{
m_modelManager = modelManager;
m_callStack.append(QmlEvent());
m_stackTop = &m_stackBottom;
m_compileStack.append(QmlEvent());
m_callStackTop = &m_stackBottom;
m_compileStackTop = &m_stackBottom;
connect(modelManager, &QmlProfilerModelManager::stateChanged,
this, &FlameGraphModel::onModelManagerStateChanged);
connect(modelManager->notesModel(), &Timeline::TimelineNotesModel::changed,
......@@ -64,8 +66,11 @@ void FlameGraphModel::clear()
beginResetModel();
m_stackBottom = FlameGraphData(0, -1, 1);
m_callStack.clear();
m_compileStack.clear();
m_callStack.append(QmlEvent());
m_stackTop = &m_stackBottom;
m_compileStack.append(QmlEvent());
m_callStackTop = &m_stackBottom;
m_compileStackTop = &m_stackBottom;
m_typeIdsWithNotes.clear();
endResetModel();
}
......@@ -99,16 +104,20 @@ void FlameGraphModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
if (m_stackBottom.children.isEmpty())
beginResetModel();
const QmlEvent *potentialParent = &(m_callStack.top());
const bool isCompiling = (type.rangeType() == Compiling);
QStack<QmlEvent> &stack = isCompiling ? m_compileStack : m_callStack;
FlameGraphData *&stackTop = isCompiling ? m_compileStackTop : m_callStackTop;
const QmlEvent *potentialParent = &(stack.top());
if (event.rangeStage() == RangeEnd) {
m_stackTop->duration += event.timestamp() - potentialParent->timestamp();
m_callStack.pop();
m_stackTop = m_stackTop->parent;
potentialParent = &(m_callStack.top());
stackTop->duration += event.timestamp() - potentialParent->timestamp();
stack.pop();
stackTop = stackTop->parent;
potentialParent = &(stack.top());
} else {
QTC_ASSERT(event.rangeStage() == RangeStart, return);
m_callStack.push(event);
m_stackTop = pushChild(m_stackTop, event);
stack.push(event);
stackTop = pushChild(stackTop, event);
}
}
......
......@@ -102,8 +102,10 @@ private:
// used by binding loop detection
QStack<QmlEvent> m_callStack;
QStack<QmlEvent> m_compileStack;
FlameGraphData m_stackBottom;
FlameGraphData *m_stackTop;
FlameGraphData *m_callStackTop;
FlameGraphData *m_compileStackTop;
int m_modelId;
QmlProfilerModelManager *m_modelManager;
......
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