QmlProfiler: allow for multiple sequential traces to be aggregated

Task-number: QTCREATORBUG-13317
Change-Id: Ic7d1d5c94d8d522741b6c4207a21a43f521da5fb
Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
This commit is contained in:
Ulf Hermann
2015-11-18 12:34:52 +01:00
parent 030acfdf73
commit ffc11d5e9e
9 changed files with 93 additions and 12 deletions

View File

@@ -63,6 +63,7 @@ public:
quint64 tcpPort; quint64 tcpPort;
QString sysroot; QString sysroot;
quint32 flushInterval; quint32 flushInterval;
bool aggregateTraces;
QmlProfilerModelManager *modelManager; QmlProfilerModelManager *modelManager;
}; };
@@ -77,6 +78,7 @@ QmlProfilerClientManager::QmlProfilerClientManager(QObject *parent) :
d->connection = 0; d->connection = 0;
d->connectionAttempts = 0; d->connectionAttempts = 0;
d->flushInterval = 0; d->flushInterval = 0;
d->aggregateTraces = true;
d->modelManager = 0; d->modelManager = 0;
@@ -101,6 +103,16 @@ void QmlProfilerClientManager::setFlushInterval(quint32 flushInterval)
d->flushInterval = flushInterval; d->flushInterval = flushInterval;
} }
bool QmlProfilerClientManager::aggregateTraces() const
{
return d->aggregateTraces;
}
void QmlProfilerClientManager::setAggregateTraces(bool aggregateTraces)
{
d->aggregateTraces = aggregateTraces;
}
void QmlProfilerClientManager::setTcpConnection(QString host, quint64 port) void QmlProfilerClientManager::setTcpConnection(QString host, quint64 port)
{ {
d->tcpHost = host; d->tcpHost = host;
@@ -349,7 +361,7 @@ void QmlProfilerClientManager::retryMessageBoxFinished(int result)
void QmlProfilerClientManager::qmlComplete(qint64 maximumTime) void QmlProfilerClientManager::qmlComplete(qint64 maximumTime)
{ {
d->modelManager->traceTime()->increaseEndTime(maximumTime); d->modelManager->traceTime()->increaseEndTime(maximumTime);
if (d->modelManager) if (d->modelManager && !d->aggregateTraces)
d->modelManager->acquiringDone(); d->modelManager->acquiringDone();
} }

View File

@@ -61,6 +61,9 @@ public:
void setModelManager(QmlProfilerModelManager *m); void setModelManager(QmlProfilerModelManager *m);
void setFlushInterval(quint32 flushInterval); void setFlushInterval(quint32 flushInterval);
bool aggregateTraces() const;
void setAggregateTraces(bool aggregateTraces);
signals: signals:
void connectionFailed(); void connectionFailed();
void connectionClosed(); void connectionClosed();

View File

@@ -46,6 +46,9 @@ QmlProfilerConfigWidget::QmlProfilerConfigWidget(QmlProfilerSettings *settings,
connect(m_ui->flushInterval, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), connect(m_ui->flushInterval, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
m_settings, &QmlProfilerSettings::setFlushInterval); m_settings, &QmlProfilerSettings::setFlushInterval);
connect(m_ui->aggregateTraces, &QCheckBox::toggled,
m_settings, &QmlProfilerSettings::setAggregateTraces);
connect(m_settings, &QmlProfilerSettings::changed, this, &QmlProfilerConfigWidget::updateUi); connect(m_settings, &QmlProfilerSettings::changed, this, &QmlProfilerConfigWidget::updateUi);
} }
@@ -59,6 +62,7 @@ void QmlProfilerConfigWidget::updateUi()
m_ui->flushEnabled->setChecked(m_settings->flushEnabled()); m_ui->flushEnabled->setChecked(m_settings->flushEnabled());
m_ui->flushInterval->setEnabled(m_settings->flushEnabled()); m_ui->flushInterval->setEnabled(m_settings->flushEnabled());
m_ui->flushInterval->setValue(m_settings->flushInterval()); m_ui->flushInterval->setValue(m_settings->flushInterval());
m_ui->aggregateTraces->setChecked(m_settings->aggregateTraces());
} }
} // Internal } // Internal

View File

@@ -47,6 +47,23 @@ itself takes time. </string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0">
<widget class="QLabel" name="aggregateTracesLabel">
<property name="text">
<string>Process data only when process ends:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="aggregateTraces">
<property name="toolTip">
<string>Only process data when the process being profiled ends, not when the current recording
session ends. This way multiple recording sessions can be aggregated in a single trace,
for example if multiple QML engines start and stop sequentially during a single run of
the program.</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>

View File

@@ -41,6 +41,7 @@ const char TASK_SAVE[] = "QmlProfiler.TaskSave";
const char FLUSH_ENABLED[] = "Analyzer.QmlProfiler.FlushEnabled"; const char FLUSH_ENABLED[] = "Analyzer.QmlProfiler.FlushEnabled";
const char FLUSH_INTERVAL[] = "Analyzer.QmlProfiler.FlushInterval"; const char FLUSH_INTERVAL[] = "Analyzer.QmlProfiler.FlushInterval";
const char LAST_TRACE_FILE[] = "Analyzer.QmlProfiler.LastTraceFile"; const char LAST_TRACE_FILE[] = "Analyzer.QmlProfiler.LastTraceFile";
const char AGGREGATE_TRACES[] = "Analyzer.QmlProfiler.AggregateTraces";
const char SETTINGS[] = "Analyzer.QmlProfiler.Settings"; const char SETTINGS[] = "Analyzer.QmlProfiler.Settings";
const char ANALYZER[] = "Analyzer"; const char ANALYZER[] = "Analyzer";

View File

@@ -45,6 +45,7 @@ QmlProfilerSettings::QmlProfilerSettings()
defaults.insert(QLatin1String(Constants::FLUSH_INTERVAL), 1000); defaults.insert(QLatin1String(Constants::FLUSH_INTERVAL), 1000);
defaults.insert(QLatin1String(Constants::FLUSH_ENABLED), false); defaults.insert(QLatin1String(Constants::FLUSH_ENABLED), false);
defaults.insert(QLatin1String(Constants::LAST_TRACE_FILE), QString()); defaults.insert(QLatin1String(Constants::LAST_TRACE_FILE), QString());
defaults.insert(QLatin1String(Constants::AGGREGATE_TRACES), false);
// Read stored values // Read stored values
QSettings *settings = Core::ICore::settings(); QSettings *settings = Core::ICore::settings();
@@ -106,6 +107,19 @@ void QmlProfilerSettings::setLastTraceFile(const QString &lastTracePath)
} }
} }
bool QmlProfilerSettings::aggregateTraces() const
{
return m_aggregateTraces;
}
void QmlProfilerSettings::setAggregateTraces(bool aggregateTraces)
{
if (m_aggregateTraces != aggregateTraces) {
m_aggregateTraces = aggregateTraces;
emit changed();
}
}
void QmlProfilerSettings::writeGlobalSettings() const void QmlProfilerSettings::writeGlobalSettings() const
{ {
QSettings *settings = Core::ICore::settings(); QSettings *settings = Core::ICore::settings();
@@ -122,6 +136,7 @@ void QmlProfilerSettings::toMap(QVariantMap &map) const
map[QLatin1String(Constants::FLUSH_INTERVAL)] = m_flushInterval; map[QLatin1String(Constants::FLUSH_INTERVAL)] = m_flushInterval;
map[QLatin1String(Constants::FLUSH_ENABLED)] = m_flushEnabled; map[QLatin1String(Constants::FLUSH_ENABLED)] = m_flushEnabled;
map[QLatin1String(Constants::LAST_TRACE_FILE)] = m_lastTraceFile; map[QLatin1String(Constants::LAST_TRACE_FILE)] = m_lastTraceFile;
map[QLatin1String(Constants::AGGREGATE_TRACES)] = m_aggregateTraces;
} }
void QmlProfilerSettings::fromMap(const QVariantMap &map) void QmlProfilerSettings::fromMap(const QVariantMap &map)
@@ -129,6 +144,7 @@ void QmlProfilerSettings::fromMap(const QVariantMap &map)
m_flushEnabled = map.value(QLatin1String(Constants::FLUSH_ENABLED)).toBool(); m_flushEnabled = map.value(QLatin1String(Constants::FLUSH_ENABLED)).toBool();
m_flushInterval = map.value(QLatin1String(Constants::FLUSH_INTERVAL)).toUInt(); m_flushInterval = map.value(QLatin1String(Constants::FLUSH_INTERVAL)).toUInt();
m_lastTraceFile = map.value(QLatin1String(Constants::LAST_TRACE_FILE)).toString(); m_lastTraceFile = map.value(QLatin1String(Constants::LAST_TRACE_FILE)).toString();
m_aggregateTraces = map.value(QLatin1String(Constants::AGGREGATE_TRACES)).toBool();
emit changed(); emit changed();
} }

View File

@@ -53,6 +53,9 @@ public:
QString lastTraceFile() const; QString lastTraceFile() const;
void setLastTraceFile(const QString &lastTraceFile); void setLastTraceFile(const QString &lastTraceFile);
bool aggregateTraces() const;
void setAggregateTraces(bool aggregateTraces);
void writeGlobalSettings() const; void writeGlobalSettings() const;
signals: signals:
@@ -66,6 +69,7 @@ private:
bool m_flushEnabled; bool m_flushEnabled;
quint32 m_flushInterval; quint32 m_flushInterval;
QString m_lastTraceFile; QString m_lastTraceFile;
bool m_aggregateTraces;
}; };
} // Internal } // Internal

View File

@@ -30,6 +30,8 @@
#include "qmlprofilerstatewidget.h" #include "qmlprofilerstatewidget.h"
#include <utils/qtcassert.h>
#include <QPainter> #include <QPainter>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QLabel> #include <QLabel>
@@ -202,11 +204,23 @@ void QmlProfilerStateWidget::updateDisplay()
return; return;
} }
} else if (d->m_modelManager->progress() != 0 && !d->m_modelManager->isEmpty()) { } else if (d->m_modelManager->progress() != 0 && !d->m_modelManager->isEmpty()) {
// When datamodel is acquiring data // When datamodel is acquiring or processing data
if (d->m_profilerState->currentState() != QmlProfilerStateManager::Idle) if (state == QmlProfilerModelManager::ProcessingData) {
showText(tr("Loading data"), true); showText(tr("Processing data"), true);
else // Application died before all data could be read } else if (d->m_profilerState->currentState() != QmlProfilerStateManager::Idle) {
showText(tr("Application stopped before loading all data"), true); if (state == QmlProfilerModelManager::AcquiringData) {
// we don't know how much more, so progress numbers are strange here
showText(tr("Waiting for more data"));
} else if (state == QmlProfilerModelManager::ClearingData) {
// when starting a second recording from the same process without aggregation
showText(tr("Clearing old trace"));
}
} else if (state == QmlProfilerModelManager::AcquiringData) {
// Application died before all data could be read
showText(tr("Application stopped before loading all data"));
} else if (state == QmlProfilerModelManager::ClearingData) {
showText(tr("Clearing old trace"));
}
return; return;
} else if (state == QmlProfilerModelManager::AcquiringData) { } else if (state == QmlProfilerModelManager::AcquiringData) {
showText(tr("Waiting for data")); showText(tr("Waiting for data"));

View File

@@ -209,6 +209,7 @@ AnalyzerRunControl *QmlProfilerTool::createRunControl(const AnalyzerStartParamet
d->m_profilerConnections->setFlushInterval(settings->flushEnabled() ? d->m_profilerConnections->setFlushInterval(settings->flushEnabled() ?
settings->flushInterval() : 0); settings->flushInterval() : 0);
d->m_profilerConnections->setAggregateTraces(settings->aggregateTraces());
QmlProfilerRunControl *engine = new QmlProfilerRunControl(sp, runConfiguration); QmlProfilerRunControl *engine = new QmlProfilerRunControl(sp, runConfiguration);
@@ -373,7 +374,9 @@ void QmlProfilerTool::recordingButtonChanged(bool recording)
if (recording && d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) { if (recording && d->m_profilerState->currentState() == QmlProfilerStateManager::AppRunning) {
if (checkForUnsavedNotes()) { if (checkForUnsavedNotes()) {
clearData(); // clear right away, before the application starts if (!d->m_profilerConnections->aggregateTraces() ||
d->m_profilerModelManager->state() == QmlProfilerModelManager::Done)
clearData(); // clear before the recording starts, unless we aggregate recordings
if (d->m_profilerState->clientRecording()) if (d->m_profilerState->clientRecording())
d->m_profilerState->setClientRecording(false); d->m_profilerState->setClientRecording(false);
d->m_profilerState->setClientRecording(true); d->m_profilerState->setClientRecording(true);
@@ -652,10 +655,14 @@ void QmlProfilerTool::clientsDisconnected()
if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppDying || if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppDying ||
d->m_profilerState->currentState() == QmlProfilerStateManager::Idle) { d->m_profilerState->currentState() == QmlProfilerStateManager::Idle) {
if (d->m_profilerModelManager->state() == QmlProfilerModelManager::AcquiringData) { if (d->m_profilerModelManager->state() == QmlProfilerModelManager::AcquiringData) {
if (d->m_profilerConnections->aggregateTraces()) {
d->m_profilerModelManager->acquiringDone();
} else {
showNonmodalWarning(tr("Application finished before loading profiled data.\n" showNonmodalWarning(tr("Application finished before loading profiled data.\n"
"Please use the stop button instead.")); "Please use the stop button instead."));
d->m_profilerModelManager->clear(); d->m_profilerModelManager->clear();
} }
}
// ... and return to the "base" state // ... and return to the "base" state
if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppDying) if (d->m_profilerState->currentState() == QmlProfilerStateManager::AppDying)
@@ -822,12 +829,15 @@ void QmlProfilerTool::serverRecordingChanged()
showSaveDialog(); showSaveDialog();
setRecording(true); setRecording(true);
if (!d->m_profilerConnections->aggregateTraces() ||
d->m_profilerModelManager->state() == QmlProfilerModelManager::Done)
clearData(); clearData();
d->m_profilerModelManager->prepareForWriting(); d->m_profilerModelManager->prepareForWriting();
} else { } else {
setRecording(false); setRecording(false);
// changes back once loading is finished, see profilerDataModelStateChanged() // changes back once loading is finished, see profilerDataModelStateChanged()
if (!d->m_profilerConnections->aggregateTraces())
d->m_recordButton->setEnabled(false); d->m_recordButton->setEnabled(false);
} }
} }