forked from qt-creator/qt-creator
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:
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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();
|
||||
|
@@ -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();
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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();
|
||||
|
@@ -52,7 +52,7 @@ void DebugMessagesModelTest::initTestCase()
|
||||
manager.addEventType(type);
|
||||
manager.addEvent(event);
|
||||
}
|
||||
manager.acquiringDone();
|
||||
manager.finalize();
|
||||
QCOMPARE(manager.state(), QmlProfilerModelManager::Done);
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
|
@@ -61,7 +61,7 @@ void InputEventsModelTest::initTestCase()
|
||||
manager.addEvent(event);
|
||||
}
|
||||
|
||||
manager.acquiringDone();
|
||||
manager.finalize();
|
||||
QCOMPARE(manager.state(), QmlProfilerModelManager::Done);
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -187,7 +187,7 @@ void PixmapCacheModelTest::initTestCase()
|
||||
}
|
||||
|
||||
|
||||
manager.acquiringDone();
|
||||
manager.finalize();
|
||||
|
||||
QCOMPARE(manager.state(), QmlProfilerModelManager::Done);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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());
|
||||
|
Reference in New Issue
Block a user