QmlProfiler: Rebuild the flamegraph model when visible features change

This is more expensive than just setting the filtered items' height to
0. However, this way we implicitly also change the size of the root
element, group equal items that end up on the same level by filtering,
recalculate the cutoff for too small items and resort all items by
width.

Change-Id: Ida2c5acd9848c5644ecff052d78e9fe5ad962606
Task-number: QTCREATORBUG-18713
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
Ulf Hermann
2017-08-11 11:12:49 +02:00
parent e7c950eb11
commit 63551d7711
4 changed files with 39 additions and 14 deletions

View File

@@ -38,6 +38,11 @@
namespace QmlProfiler {
namespace Internal {
static inline quint64 supportedFeatures()
{
return Constants::QML_JS_RANGE_FEATURES | (1ULL << ProfileMemory);
}
FlameGraphModel::FlameGraphModel(QmlProfilerModelManager *modelManager,
QObject *parent) : QAbstractItemModel(parent)
{
@@ -51,8 +56,9 @@ FlameGraphModel::FlameGraphModel(QmlProfilerModelManager *modelManager,
connect(modelManager->notesModel(), &Timeline::TimelineNotesModel::changed,
this, [this](int typeId, int, int){loadNotes(typeId, true);});
m_modelId = modelManager->registerModelProxy();
m_acceptedFeatures = supportedFeatures();
modelManager->announceFeatures(Constants::QML_JS_RANGE_FEATURES | 1 << ProfileMemory,
modelManager->announceFeatures(m_acceptedFeatures,
[this](const QmlEvent &event, const QmlEventType &type) {
loadEvent(event, type);
}, [this](){
@@ -98,7 +104,8 @@ void FlameGraphModel::loadNotes(int typeIndex, bool emitSignal)
void FlameGraphModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
{
Q_UNUSED(type);
if (!(m_acceptedFeatures & (1ULL << type.feature())))
return;
if (m_stackBottom.children.isEmpty())
beginResetModel();
@@ -150,6 +157,31 @@ void FlameGraphModel::onModelManagerStateChanged()
clear();
}
void FlameGraphModel::restrictToFeatures(quint64 visibleFeatures)
{
visibleFeatures = visibleFeatures & supportedFeatures();
if (visibleFeatures == m_acceptedFeatures)
return;
m_acceptedFeatures = visibleFeatures;
if (m_modelManager->state() != QmlProfilerModelManager::Done)
return;
clear();
beginResetModel();
if (!m_modelManager->replayEvents(m_modelManager->traceTime()->startTime(),
m_modelManager->traceTime()->endTime(),
std::bind(&FlameGraphModel::loadEvent,
this, std::placeholders::_1,
std::placeholders::_2))) {
emit m_modelManager->error(tr("Could not re-read events from temporary trace file."));
endResetModel();
clear();
} else {
finalize();
}
}
static QString nameForType(RangeType typeNumber)
{
switch (typeNumber) {

View File

@@ -91,6 +91,7 @@ public slots:
void loadEvent(const QmlEvent &event, const QmlEventType &type);
void finalize();
void onModelManagerStateChanged();
void restrictToFeatures(quint64 visibleFeatures);
void loadNotes(int typeId, bool emitSignal);
void clear();
@@ -105,6 +106,7 @@ private:
FlameGraphData *m_callStackTop;
FlameGraphData *m_compileStackTop;
quint64 m_acceptedFeatures;
int m_modelId;
QmlProfilerModelManager *m_modelManager;

View File

@@ -80,13 +80,7 @@ void FlameGraphView::selectByTypeId(int typeIndex)
void FlameGraphView::onVisibleFeaturesChanged(quint64 features)
{
int rangeTypeMask = 0;
for (int rangeType = 0; rangeType < MaximumRangeType; ++rangeType) {
if (features & (1ULL << featureFromRangeType(RangeType(rangeType))))
rangeTypeMask |= (1 << rangeType);
}
if (m_content->rootObject())
m_content->rootObject()->setProperty("visibleRangeTypes", rangeTypeMask);
m_model->restrictToFeatures(features);
}
void FlameGraphView::contextMenuEvent(QContextMenuEvent *ev)

View File

@@ -36,7 +36,6 @@ ScrollView {
signal gotoSourceLocation(string filename, int line, int column)
property int selectedTypeId: -1
property int visibleRangeTypes: -1
property int sizeRole: QmlProfilerFlameGraphModel.DurationRole
readonly property var trRoleNames: [
@@ -86,11 +85,9 @@ ScrollView {
property int typeId: FlameGraph.data(QmlProfilerFlameGraphModel.TypeIdRole) || -1
property bool isBindingLoop: parent.checkBindingLoop(typeId)
property bool rangeTypeVisible:
root.visibleRangeTypes & (1 << FlameGraph.data(QmlProfilerFlameGraphModel.RangeTypeRole))
itemHeight: rangeTypeVisible ? flamegraph.delegateHeight : 0
isSelected: typeId !== -1 && typeId === root.selectedTypeId && rangeTypeVisible
itemHeight: flamegraph.delegateHeight
isSelected: typeId !== -1 && typeId === root.selectedTypeId
borderColor: {
if (isSelected)