QmlProfiler: Get rid of processing step

The child models are made aware of possible changes in the details
strings, and in turn, we can do the finalization immediately after
acquiring is done.

Change-Id: Ibe57f158e64e5d01d4c97aa617c9b2bcc8e4e96e
Task-number: QTCREATORBUG-20106
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
Ulf Hermann
2018-03-27 15:58:43 +02:00
parent 72e0a6fec5
commit 1ccd058bdf
22 changed files with 98 additions and 51 deletions

View File

@@ -124,6 +124,8 @@ QObject *FlameGraph::appendChild(QObject *parentObject, QQuickItem *parentItem,
attached->setRelativePosition(position);
attached->setRelativeSize(size);
attached->setModelIndex(childIndex);
connect(m_model, &QAbstractItemModel::dataChanged,
attached, &FlameGraphAttached::modelIndexChanged);
m_delegate->completeCreate();
return childObject;
}

View File

@@ -181,6 +181,16 @@ ScrollView {
}
onSelectedItemChanged: scroller.propagateSelection(index, selectedItem);
Connections {
target: model
onDetailsChanged: {
if (selectedItem != -1) {
scroller.propagateSelection(-1, -1);
scroller.propagateSelection(index, selectedItem);
}
}
}
}
}

View File

@@ -160,6 +160,8 @@ TimelineModel::TimelineModelPrivate::TimelineModelPrivate(int modelId) :
TimelineModel::TimelineModel(int modelId, QObject *parent) :
QObject(parent), d_ptr(new TimelineModelPrivate(modelId))
{
connect(this, &TimelineModel::contentChanged, this, &TimelineModel::labelsChanged);
connect(this, &TimelineModel::contentChanged, this, &TimelineModel::detailsChanged);
}
TimelineModel::~TimelineModel()
@@ -618,6 +620,8 @@ void TimelineModel::clear()
if (!wasEmpty) {
emit contentChanged();
emit heightChanged();
emit labelsChanged();
emit detailsChanged();
}
}

View File

@@ -44,7 +44,7 @@ class TIMELINE_EXPORT TimelineModel : public QObject
Q_PROPERTY(int expandedRowCount READ expandedRowCount NOTIFY expandedRowCountChanged)
Q_PROPERTY(int collapsedRowCount READ collapsedRowCount NOTIFY collapsedRowCountChanged)
Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged)
Q_PROPERTY(QVariantList labels READ labels NOTIFY contentChanged)
Q_PROPERTY(QVariantList labels READ labels NOTIFY labelsChanged)
Q_PROPERTY(int count READ count NOTIFY contentChanged)
Q_PROPERTY(int defaultRowHeight READ defaultRowHeight CONSTANT)
@@ -123,6 +123,8 @@ signals:
void collapsedRowCountChanged();
void rowCountChanged();
void displayNameChanged();
void labelsChanged();
void detailsChanged();
protected:
QRgb colorBySelectionId(int index) const;

View File

@@ -53,6 +53,8 @@ FlameGraphModel::FlameGraphModel(QmlProfilerModelManager *modelManager,
m_compileStackTop = &m_stackBottom;
connect(modelManager, &QmlProfilerModelManager::stateChanged,
this, &FlameGraphModel::onModelManagerStateChanged);
connect(modelManager, &QmlProfilerModelManager::typeDetailsFinished,
this, &FlameGraphModel::onTypeDetailsFinished);
connect(modelManager->notesModel(), &Timeline::TimelineNotesModel::changed,
this, [this](int typeId, int, int){loadNotes(typeId, true);});
m_modelId = modelManager->registerModelProxy();
@@ -157,6 +159,11 @@ void FlameGraphModel::onModelManagerStateChanged()
clear();
}
void FlameGraphModel::onTypeDetailsFinished()
{
emit dataChanged(QModelIndex(), QModelIndex(), QVector<int>(1, DetailsRole));
}
void FlameGraphModel::restrictToFeatures(quint64 visibleFeatures)
{
visibleFeatures = visibleFeatures & supportedFeatures();

View File

@@ -90,6 +90,7 @@ public:
void loadEvent(const QmlEvent &event, const QmlEventType &type);
void finalize();
void onModelManagerStateChanged();
void onTypeDetailsFinished();
void restrictToFeatures(quint64 visibleFeatures);
void loadNotes(int typeId, bool emitSignal);
void clear();

View File

@@ -148,7 +148,22 @@ ScrollView {
+ Math.floor(width / flamegraph.width * 1000) / 10 + "%)";
}
text: textVisible ? buildText() : ""
FlameGraph.onModelIndexChanged: if (textVisible) text = buildText();
FlameGraph.onModelIndexChanged: {
if (textVisible)
text = buildText();
// refresh to trigger reevaluation
if (tooltip.selectedNode == flamegraphItem) {
var selectedNode = tooltip.selectedNode;
tooltip.selectedNode = null;
tooltip.selectedNode = selectedNode;
}
if (tooltip.hoveredNode == flamegraphItem) {
var hoveredNode = tooltip.hoveredNode;
tooltip.hoveredNode = null;
tooltip.hoveredNode = hoveredNode;
}
}
onMouseEntered: {
tooltip.hoveredNode = flamegraphItem;
@@ -307,12 +322,6 @@ ScrollView {
tooltip.hoveredNode = null;
tooltip.selectedNode = null;
}
onDataChanged: {
// refresh to trigger reevaluation of note
var selectedNode = tooltip.selectedNode;
tooltip.selectedNode = null;
tooltip.selectedNode = selectedNode;
}
}
}

View File

@@ -188,7 +188,7 @@ QmlProfilerModelManager::QmlProfilerModelManager(QObject *parent) :
connect(d->detailsRewriter, &QmlProfilerDetailsRewriter::rewriteDetailsString,
this, &QmlProfilerModelManager::detailsChanged);
connect(d->detailsRewriter, &QmlProfilerDetailsRewriter::eventDetailsChanged,
this, &QmlProfilerModelManager::processingDone);
this, &QmlProfilerModelManager::typeDetailsFinished);
if (d->file.open())
d->eventStream.setDevice(&d->file);
@@ -499,17 +499,12 @@ const char *QmlProfilerModelManager::featureName(ProfileFeature feature)
return ProfileFeatureNames[feature];
}
void QmlProfilerModelManager::acquiringDone()
void QmlProfilerModelManager::finalize()
{
QTC_ASSERT(state() == AcquiringData, /**/);
setState(ProcessingData);
d->file.flush();
d->detailsRewriter->reloadDocuments();
}
void QmlProfilerModelManager::processingDone()
{
QTC_ASSERT(state() == ProcessingData, /**/);
// Load notes after the timeline models have been initialized ...
// which happens on stateChanged(Done).
@@ -617,7 +612,7 @@ void QmlProfilerModelManager::load(const QString &filename)
d->traceTime->increaseEndTime(reader->traceEnd());
setRecordedFeatures(reader->loadedFeatures());
delete reader;
acquiringDone();
finalize();
}, Qt::QueuedConnection);
connect(reader, &QmlProfilerFileReader::error, this, [this, reader](const QString &message) {
@@ -659,14 +654,9 @@ void QmlProfilerModelManager::setState(QmlProfilerModelManager::State state)
QTC_ASSERT(isEmpty(), /**/);
break;
case AcquiringData:
// we're not supposed to receive new data while processing older data
QTC_ASSERT(d->state != ProcessingData, return);
break;
case ProcessingData:
QTC_ASSERT(d->state == AcquiringData, return);
break;
case Done:
QTC_ASSERT(d->state == ProcessingData || d->state == Empty, return);
QTC_ASSERT(d->state == AcquiringData || d->state == Empty, return);
break;
default:
emit error(tr("Trying to set unknown state in events list."));
@@ -681,6 +671,7 @@ void QmlProfilerModelManager::detailsChanged(int typeId, const QString &newStrin
{
QTC_ASSERT(typeId < d->eventTypes.count(), return);
d->eventTypes[typeId].setData(newString);
emit typeDetailsChanged(typeId);
}
QmlProfilerModelManager::State QmlProfilerModelManager::state() const
@@ -739,7 +730,7 @@ void QmlProfilerModelManager::restrictToRange(qint64 startTime, qint64 endTime)
} else {
d->notesModel->setNotes(notes);
d->traceTime->restrictToRange(startTime, endTime);
acquiringDone();
finalize();
}
}

View File

@@ -83,7 +83,6 @@ public:
enum State {
Empty,
AcquiringData,
ProcessingData,
ClearingData,
Done
};
@@ -126,8 +125,7 @@ public:
bool aggregateTraces() const;
void setAggregateTraces(bool aggregateTraces);
void acquiringDone();
void processingDone();
void finalize();
void populateFileFinder(const ProjectExplorer::Target *target = nullptr);
QString findLocalFile(const QString &remoteFile);
@@ -154,6 +152,9 @@ signals:
void visibleFeaturesChanged(quint64 features);
void recordedFeaturesChanged(quint64 features);
void typeDetailsChanged(int typeId);
void typeDetailsFinished();
private:
void setState(State state);
void detailsChanged(int typeId, const QString &newString);

View File

@@ -132,10 +132,7 @@ void QmlProfilerStateWidget::updateDisplay()
}
} else if (!d->m_modelManager->isEmpty()) {
// When datamodel is acquiring or processing data
if (state == QmlProfilerModelManager::ProcessingData) {
showText(tr("Processing data: %1 / %2").arg(d->m_modelManager->numFinishedFinalizers())
.arg(d->m_modelManager->numRegisteredFinalizers()));
} else if (d->m_profilerState->currentState() != QmlProfilerStateManager::Idle) {
if (d->m_profilerState->currentState() != QmlProfilerStateManager::Idle) {
if (state == QmlProfilerModelManager::AcquiringData) {
// we don't know how much more, so progress numbers are strange here
showText(tr("Loading buffered data: %n events", 0,
@@ -165,12 +162,11 @@ void QmlProfilerStateWidget::update()
{
QmlProfilerModelManager::State state = d->m_modelManager ? d->m_modelManager->state()
: QmlProfilerModelManager::Empty;
if (state == QmlProfilerModelManager::AcquiringData
|| state == QmlProfilerModelManager::ProcessingData) {
if (state == QmlProfilerModelManager::AcquiringData)
d->timer.start();
} else {
else
d->timer.stop();
}
updateDisplay();
}

View File

@@ -398,6 +398,12 @@ void QmlProfilerStatisticsModel::modelManagerStateChanged()
}
}
void QmlProfilerStatisticsModel::typeDetailsChanged(int typeIndex)
{
const QModelIndex index = createIndex(typeIndex, MainDetails);
emit dataChanged(index, index, QVector<int>({SortRole, Qt::DisplayRole}));
}
void QmlProfilerStatisticsModel::notesChanged(int typeIndex)
{
static const QVector<int> noteRoles({Qt::ToolTipRole, Qt::TextColorRole});
@@ -498,6 +504,8 @@ QmlProfilerStatisticsRelativesModel::QmlProfilerStatisticsRelativesModel(
QTC_CHECK(modelManager);
QTC_CHECK(statisticsModel);
statisticsModel->setRelativesModel(this, relation);
connect(m_modelManager, &QmlProfilerModelManager::typeDetailsChanged,
this, &QmlProfilerStatisticsRelativesModel::typeDetailsChanged);
}
bool operator<(const QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesData &a,
@@ -697,6 +705,22 @@ bool QmlProfilerStatisticsRelativesModel::setData(const QModelIndex &index, cons
}
}
void QmlProfilerStatisticsRelativesModel::typeDetailsChanged(int typeId)
{
auto main_it = m_data.constFind(m_relativeTypeIndex);
if (main_it == m_data.constEnd())
return;
const QVector<QmlStatisticsRelativesData> &rows = main_it.value();
for (int row = 0, end = rows.length(); row != end; ++row) {
if (rows[row].typeIndex == typeId) {
const QModelIndex index = createIndex(row, RelativeDetails);
emit dataChanged(index, index, QVector<int>({SortRole, Qt::DisplayRole}));
return;
}
}
}
void QmlProfilerStatisticsRelativesModel::clear()
{
beginResetModel();

View File

@@ -153,6 +153,7 @@ private:
void finalize();
void modelManagerStateChanged();
void typeDetailsChanged(int typeIndex);
void notesChanged(int typeIndex);
QVariant dataForMainEntry(const QModelIndex &index, int role) const;
@@ -207,6 +208,7 @@ public:
private:
QVariant dataForMainEntry(qint64 totalDuration, int role, int column) const;
void typeDetailsChanged(int typeId);
QHash<int, QVector<QmlStatisticsRelativesData>> m_data;
QPointer<QmlProfilerModelManager> m_modelManager;

View File

@@ -37,6 +37,10 @@ QmlProfilerTimelineModel::QmlProfilerTimelineModel(QmlProfilerModelManager *mode
setDisplayName(tr(QmlProfilerModelManager::featureName(mainFeature)));
connect(modelManager, &QmlProfilerModelManager::stateChanged,
this, &QmlProfilerTimelineModel::dataChanged);
connect(modelManager, &QmlProfilerModelManager::typeDetailsFinished,
this, &Timeline::TimelineModel::labelsChanged);
connect(modelManager, &QmlProfilerModelManager::typeDetailsFinished,
this, &Timeline::TimelineModel::detailsChanged);
connect(modelManager, &QmlProfilerModelManager::visibleFeaturesChanged,
this, &QmlProfilerTimelineModel::onVisibleFeaturesChanged);
announceFeatures(1ULL << m_mainFeature);

View File

@@ -315,7 +315,6 @@ QmlProfilerTool::QmlProfilerTool()
&& d->m_profilerState->currentState()
!= QmlProfilerStateManager::AppDying);
break;
case QmlProfilerModelManager::ProcessingData:
case QmlProfilerModelManager::ClearingData:
d->m_recordButton->setEnabled(false);
break;
@@ -734,7 +733,7 @@ void QmlProfilerTool::clientsDisconnected()
{
if (d->m_profilerModelManager->state() == QmlProfilerModelManager::AcquiringData) {
if (d->m_profilerModelManager->aggregateTraces()) {
d->m_profilerModelManager->acquiringDone();
d->m_profilerModelManager->finalize();
} else {
// If the application stopped by itself, check if we have all the data
if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppDying ||
@@ -814,9 +813,6 @@ void QmlProfilerTool::profilerDataModelStateChanged()
restoreFeatureVisibility();
setButtonsEnabled(false); // Other buttons disabled
break;
case QmlProfilerModelManager::ProcessingData :
setButtonsEnabled(false);
break;
case QmlProfilerModelManager::Done :
showSaveOption();
updateTimeDisplay();
@@ -920,10 +916,10 @@ void QmlProfilerTool::serverRecordingChanged()
} else {
d->m_recordingTimer.stop();
if (!d->m_profilerModelManager->aggregateTraces())
d->m_profilerModelManager->acquiringDone();
d->m_profilerModelManager->finalize();
}
} else if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppStopRequested) {
d->m_profilerModelManager->acquiringDone();
d->m_profilerModelManager->finalize();
d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle);
}
}

View File

@@ -110,8 +110,6 @@ QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, QmlProfilerViewManag
d->m_suspendedModels.clear();
d->m_modelManager->notesModel()->loadData();
break;
case QmlProfilerModelManager::ProcessingData:
break;
case QmlProfilerModelManager::ClearingData:
d->m_zoomControl->clear();
Q_FALLTHROUGH();

View File

@@ -52,7 +52,7 @@ void DebugMessagesModelTest::initTestCase()
manager.addEventType(type);
manager.addEvent(event);
}
manager.acquiringDone();
manager.finalize();
QCOMPARE(manager.state(), QmlProfilerModelManager::Done);
}

View File

@@ -84,7 +84,7 @@ int FlameGraphModelTest::generateData(QmlProfilerModelManager *manager)
manager->addEvent(event);
}
manager->acquiringDone();
manager->finalize();
manager->notesModel()->setNotes(QVector<QmlNote>({QmlNote(0, 2, 1, 20, "dings")}));
manager->notesModel()->loadData();

View File

@@ -61,7 +61,7 @@ void InputEventsModelTest::initTestCase()
manager.addEvent(event);
}
manager.acquiringDone();
manager.finalize();
QCOMPARE(manager.state(), QmlProfilerModelManager::Done);
}

View File

@@ -96,7 +96,7 @@ void MemoryUsageModelTest::initTestCase()
event.setNumbers({-1024});
manager.addEvent(event);
manager.acquiringDone();
manager.finalize();
QCOMPARE(manager.state(), QmlProfilerModelManager::Done);
QCOMPARE(model.count(), 11);
}

View File

@@ -187,7 +187,7 @@ void PixmapCacheModelTest::initTestCase()
}
manager.acquiringDone();
manager.finalize();
QCOMPARE(manager.state(), QmlProfilerModelManager::Done);
}

View File

@@ -54,7 +54,7 @@ void QmlProfilerAnimationsModelTest::initTestCase()
event.setNumbers<int>({frameRate(i), 9 - i, (i % 2) ? RenderThread : GuiThread});
manager.addEvent(event);
}
manager.acquiringDone();
manager.finalize();
QCOMPARE(manager.state(), QmlProfilerModelManager::Done);
}

View File

@@ -39,7 +39,7 @@ void QmlProfilerTraceViewTest::testStateChanges()
// Standard acquire-process-clear work flow
modelManager.startAcquiring();
QVERIFY(traceView.isSuspended());
modelManager.acquiringDone();
modelManager.finalize();
QVERIFY(!traceView.isSuspended());
modelManager.clear();
QVERIFY(!traceView.isSuspended());
@@ -47,7 +47,7 @@ void QmlProfilerTraceViewTest::testStateChanges()
// Restrict to range
modelManager.startAcquiring();
QVERIFY(traceView.isSuspended());
modelManager.acquiringDone();
modelManager.finalize();
QVERIFY(!traceView.isSuspended());
modelManager.restrictToRange(10, 14);
QVERIFY(!traceView.isSuspended());