QmlProfiler: switch storage for typeId and selectionId

The selectionIds are an integral part of the timeline and have to be
given for each event. The typeIds are optional. Thus it makes more
sense to store the selectionIds in the basic Range classes and have the
derived models handle the typeIds instead of doing it the other way
around.

Change-Id: I824224b6f58e8d45311134887482586283fbff41
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@theqtcompany.com>
Reviewed-by: Kai Koehne <kai.koehne@theqtcompany.com>
This commit is contained in:
Ulf Hermann
2014-10-28 14:26:57 +01:00
committed by Ulf Hermann
parent 4ec75995f8
commit 307d45ecaa
7 changed files with 68 additions and 51 deletions

View File

@@ -304,10 +304,15 @@ qint64 AbstractTimelineModel::endTime(int index) const
return d->ranges[index].start + d->ranges[index].duration; return d->ranges[index].start + d->ranges[index].duration;
} }
/*!
Returns the type ID of the event with event ID \a index. The type ID is a globally valid ID which
can be used to communicate metainformation about events to other parts of the program. By default
it is -1, which means there is no global type information about the event.
*/
int AbstractTimelineModel::typeId(int index) const int AbstractTimelineModel::typeId(int index) const
{ {
Q_D(const AbstractTimelineModel); Q_UNUSED(index)
return d->ranges[index].typeId; return -1;
} }
/*! /*!
@@ -374,10 +379,17 @@ QVariantMap AbstractTimelineModel::location(int index) const
return map; return map;
} }
/*!
Returns \c true if this model can contain events of global type Id \a typeIndex. Otherwise
returns \c false.
*/
bool AbstractTimelineModel::handlesTypeId(int typeIndex) const bool AbstractTimelineModel::handlesTypeId(int typeIndex) const
{ {
Q_UNUSED(typeIndex); if (typeIndex < 0)
return false; return false;
Q_D(const AbstractTimelineModel);
return accepted(d->modelManager->qmlModel()->getEventTypes().at(typeIndex));
} }
int AbstractTimelineModel::selectionIdForLocation(const QString &filename, int line, int column) const int AbstractTimelineModel::selectionIdForLocation(const QString &filename, int line, int column) const
@@ -453,16 +465,17 @@ QColor AbstractTimelineModel::colorByHue(int hue) const
} }
/*! /*!
\fn int AbstractTimelineModel::insert(qint64 startTime, qint64 duration) Inserts an event at the time specified by \a startTime with the given \a duration and returns
Inserts a range at the given time position and returns its index. its index. The \a selectionId determines the selection group the new event belongs to.
\sa selectionId()
*/ */
int AbstractTimelineModel::insert(qint64 startTime, qint64 duration, int typeId) int AbstractTimelineModel::insert(qint64 startTime, qint64 duration, int selectionId)
{ {
Q_D(AbstractTimelineModel); Q_D(AbstractTimelineModel);
/* Doing insert-sort here is preferable as most of the time the times will actually be /* Doing insert-sort here is preferable as most of the time the times will actually be
* presorted in the right way. So usually this will just result in appending. */ * presorted in the right way. So usually this will just result in appending. */
int index = d->insertSorted(d->ranges, int index = d->insertSorted(d->ranges,
AbstractTimelineModelPrivate::Range(startTime, duration, typeId)); AbstractTimelineModelPrivate::Range(startTime, duration, selectionId));
if (index < d->ranges.size() - 1) if (index < d->ranges.size() - 1)
d->incrementStartIndices(index); d->incrementStartIndices(index);
d->insertSorted(d->endTimes, d->insertSorted(d->endTimes,
@@ -471,15 +484,15 @@ int AbstractTimelineModel::insert(qint64 startTime, qint64 duration, int typeId)
} }
/*! /*!
\fn int AbstractTimelineModel::insertStart(qint64 startTime, int typeId) Inserts a range start at the time given by \a startTime and returns its index. The range end is
Inserts the given data as range start at the given time position and not set. The \a selectionId determines the selection group the new event belongs to.
returns its index. The range end is not set. \sa selectionId()
*/ */
int AbstractTimelineModel::insertStart(qint64 startTime, int typeId) int AbstractTimelineModel::insertStart(qint64 startTime, int selectionId)
{ {
Q_D(AbstractTimelineModel); Q_D(AbstractTimelineModel);
int index = d->insertSorted(d->ranges, int index = d->insertSorted(d->ranges,
AbstractTimelineModelPrivate::Range(startTime, 0, typeId)); AbstractTimelineModelPrivate::Range(startTime, 0, selectionId));
if (index < d->ranges.size() - 1) if (index < d->ranges.size() - 1)
d->incrementStartIndices(index); d->incrementStartIndices(index);
return index; return index;
@@ -567,10 +580,18 @@ int AbstractTimelineModel::rowCount() const
return d->expanded ? d->expandedRowCount : d->collapsedRowCount; return d->expanded ? d->expandedRowCount : d->collapsedRowCount;
} }
/*!
Returns the ID of the selection group the event with event Id \a index belongs to. Selection
groups are local to the model and the model can arbitrarily assign events to selection groups
when inserting them.
If one event from a selection group is selected, all visible other events from the same
selection group are highlighted. Rows are expected to correspond to selection IDs when the view
is expanded.
*/
int AbstractTimelineModel::selectionId(int index) const int AbstractTimelineModel::selectionId(int index) const
{ {
Q_D(const AbstractTimelineModel); Q_D(const AbstractTimelineModel);
return d->ranges[index].typeId; return d->ranges[index].selectionId;
} }
void AbstractTimelineModel::clear() void AbstractTimelineModel::clear()

View File

@@ -73,13 +73,12 @@ public:
qint64 duration(int index) const; qint64 duration(int index) const;
qint64 startTime(int index) const; qint64 startTime(int index) const;
qint64 endTime(int index) const; qint64 endTime(int index) const;
int typeId(int index) const; int selectionId(int index) const;
int firstIndex(qint64 startTime) const; int firstIndex(qint64 startTime) const;
int firstIndexNoParents(qint64 startTime) const; int firstIndexNoParents(qint64 startTime) const;
int lastIndex(qint64 endTime) const; int lastIndex(qint64 endTime) const;
bool accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const;
bool expanded() const; bool expanded() const;
bool hidden() const; bool hidden() const;
void setExpanded(bool expanded); void setExpanded(bool expanded);
@@ -97,8 +96,9 @@ public:
// Methods which can optionally be implemented by child models. // Methods which can optionally be implemented by child models.
// returned map should contain "file", "line", "column" properties, or be empty // returned map should contain "file", "line", "column" properties, or be empty
virtual QVariantMap location(int index) const; virtual QVariantMap location(int index) const;
virtual int selectionId(int index) const; virtual int typeId(int index) const;
virtual bool handlesTypeId(int typeId) const; virtual bool handlesTypeId(int typeId) const;
virtual bool accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const;
virtual int selectionIdForLocation(const QString &filename, int line, int column) const; virtual int selectionIdForLocation(const QString &filename, int line, int column) const;
virtual int bindingLoopDest(int index) const; virtual int bindingLoopDest(int index) const;
virtual float relativeHeight(int index) const; virtual float relativeHeight(int index) const;
@@ -120,8 +120,8 @@ protected:
QColor colorByFraction(double fraction) const; QColor colorByFraction(double fraction) const;
QColor colorByHue(int hue) const; QColor colorByHue(int hue) const;
int insert(qint64 startTime, qint64 duration, int typeId); int insert(qint64 startTime, qint64 duration, int selectionId);
int insertStart(qint64 startTime, int typeId); int insertStart(qint64 startTime, int selectionId);
void insertEnd(int index, qint64 duration); void insertEnd(int index, qint64 duration);
void computeNesting(); void computeNesting();

View File

@@ -48,12 +48,12 @@ public:
}; };
struct Range { struct Range {
Range() : start(-1), duration(-1), typeId(-1), parent(-1) {} Range() : start(-1), duration(-1), selectionId(-1), parent(-1) {}
Range(qint64 start, qint64 duration, int typeId) : Range(qint64 start, qint64 duration, int selectionId) :
start(start), duration(duration), typeId(typeId), parent(-1) {} start(start), duration(duration), selectionId(selectionId), parent(-1) {}
qint64 start; qint64 start;
qint64 duration; qint64 duration;
int typeId; int selectionId;
int parent; int parent;
inline qint64 timestamp() const {return start;} inline qint64 timestamp() const {return start;}
}; };

View File

@@ -82,6 +82,7 @@ void QmlProfilerAnimationsModel::loadData()
const QVector<QmlProfilerDataModel::QmlEventData> &referenceList = simpleModel->getEvents(); const QVector<QmlProfilerDataModel::QmlEventData> &referenceList = simpleModel->getEvents();
const QVector<QmlProfilerDataModel::QmlEventTypeData> &typeList = simpleModel->getEventTypes(); const QVector<QmlProfilerDataModel::QmlEventTypeData> &typeList = simpleModel->getEventTypes();
QmlDebug::AnimationThread lastThread;
QmlPaintEventData lastEvent; QmlPaintEventData lastEvent;
qint64 minNextStartTimes[] = {0, 0}; qint64 minNextStartTimes[] = {0, 0};
@@ -90,7 +91,7 @@ void QmlProfilerAnimationsModel::loadData()
if (!accepted(type)) if (!accepted(type))
continue; continue;
lastEvent.threadId = (QmlDebug::AnimationThread)event.numericData3; lastThread = (QmlDebug::AnimationThread)event.numericData3;
// initial estimation of the event duration: 1/framerate // initial estimation of the event duration: 1/framerate
qint64 estimatedDuration = event.numericData1 > 0 ? 1e9/event.numericData1 : 1; qint64 estimatedDuration = event.numericData1 > 0 ? 1e9/event.numericData1 : 1;
@@ -99,7 +100,7 @@ void QmlProfilerAnimationsModel::loadData()
qint64 realEndTime = event.startTime; qint64 realEndTime = event.startTime;
// ranges should not overlap. If they do, our estimate wasn't accurate enough // ranges should not overlap. If they do, our estimate wasn't accurate enough
qint64 realStartTime = qMax(event.startTime - estimatedDuration, minNextStartTimes[lastEvent.threadId]); qint64 realStartTime = qMax(event.startTime - estimatedDuration, minNextStartTimes[lastThread]);
// Sometimes our estimate is far off or the server has miscalculated the frame rate // Sometimes our estimate is far off or the server has miscalculated the frame rate
if (realStartTime >= realEndTime) if (realStartTime >= realEndTime)
@@ -107,18 +108,19 @@ void QmlProfilerAnimationsModel::loadData()
// Don't "fix" the framerate even if we've fixed the duration. // Don't "fix" the framerate even if we've fixed the duration.
// The server should know better after all and if it doesn't we want to see that. // The server should know better after all and if it doesn't we want to see that.
lastEvent.typeId = event.typeIndex;
lastEvent.framerate = (int)event.numericData1; lastEvent.framerate = (int)event.numericData1;
lastEvent.animationcount = (int)event.numericData2; lastEvent.animationcount = (int)event.numericData2;
QTC_ASSERT(lastEvent.animationcount > 0, continue); QTC_ASSERT(lastEvent.animationcount > 0, continue);
m_data.insert(insert(realStartTime, realEndTime - realStartTime, event.typeIndex), lastEvent); m_data.insert(insert(realStartTime, realEndTime - realStartTime, lastThread), lastEvent);
if (lastEvent.threadId == QmlDebug::GuiThread) if (lastThread == QmlDebug::GuiThread)
m_maxGuiThreadAnimations = qMax(lastEvent.animationcount, m_maxGuiThreadAnimations); m_maxGuiThreadAnimations = qMax(lastEvent.animationcount, m_maxGuiThreadAnimations);
else else
m_maxRenderThreadAnimations = qMax(lastEvent.animationcount, m_maxRenderThreadAnimations); m_maxRenderThreadAnimations = qMax(lastEvent.animationcount, m_maxRenderThreadAnimations);
minNextStartTimes[lastEvent.threadId] = event.startTime + 1; minNextStartTimes[lastThread] = event.startTime + 1;
updateProgress(count(), referenceList.count()); updateProgress(count(), referenceList.count());
} }
@@ -131,14 +133,14 @@ void QmlProfilerAnimationsModel::loadData()
/////////////////// QML interface /////////////////// QML interface
int QmlProfilerAnimationsModel::rowFromThreadId(QmlDebug::AnimationThread threadId) const int QmlProfilerAnimationsModel::rowFromThreadId(int threadId) const
{ {
return (threadId == QmlDebug::GuiThread || m_maxGuiThreadAnimations == 0) ? 1 : 2; return (threadId == QmlDebug::GuiThread || m_maxGuiThreadAnimations == 0) ? 1 : 2;
} }
int QmlProfilerAnimationsModel::row(int index) const int QmlProfilerAnimationsModel::row(int index) const
{ {
return rowFromThreadId(m_data[index].threadId); return rowFromThreadId(selectionId(index));
} }
int QmlProfilerAnimationsModel::rowMaxValue(int rowNumber) const int QmlProfilerAnimationsModel::rowMaxValue(int rowNumber) const
@@ -153,9 +155,9 @@ int QmlProfilerAnimationsModel::rowMaxValue(int rowNumber) const
} }
} }
int QmlProfilerAnimationsModel::selectionId(int index) const int QmlProfilerAnimationsModel::typeId(int index) const
{ {
return m_data[index].threadId; return m_data[index].typeId;
} }
QColor QmlProfilerAnimationsModel::color(int index) const QColor QmlProfilerAnimationsModel::color(int index) const
@@ -170,15 +172,15 @@ QColor QmlProfilerAnimationsModel::color(int index) const
float QmlProfilerAnimationsModel::relativeHeight(int index) const float QmlProfilerAnimationsModel::relativeHeight(int index) const
{ {
const QmlPaintEventData &data = m_data[index]; const int thread = selectionId(index);
// Add some height to the events if we're far from the scale threshold of 2 * DefaultRowHeight. // Add some height to the events if we're far from the scale threshold of 2 * DefaultRowHeight.
// Like that you can see the smaller events more easily. // Like that you can see the smaller events more easily.
int scaleThreshold = 2 * defaultRowHeight() - rowHeight(rowFromThreadId(data.threadId)); int scaleThreshold = 2 * defaultRowHeight() - rowHeight(rowFromThreadId(thread));
float boost = scaleThreshold > 0 ? (0.15 * scaleThreshold / defaultRowHeight()) : 0; float boost = scaleThreshold > 0 ? (0.15 * scaleThreshold / defaultRowHeight()) : 0;
return boost + (1.0 - boost) * (float)data.animationcount / return boost + (1.0 - boost) * (float)m_data[index].animationcount /
(float)(data.threadId == QmlDebug::GuiThread ? m_maxGuiThreadAnimations : (float)(thread == QmlDebug::GuiThread ? m_maxGuiThreadAnimations :
m_maxRenderThreadAnimations); m_maxRenderThreadAnimations);
} }
@@ -213,8 +215,8 @@ QVariantMap QmlProfilerAnimationsModel::details(int index) const
result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(duration(index))); result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(duration(index)));
result.insert(tr("Framerate"), QString::fromLatin1("%1 FPS").arg(m_data[index].framerate)); result.insert(tr("Framerate"), QString::fromLatin1("%1 FPS").arg(m_data[index].framerate));
result.insert(tr("Animations"), QString::fromLatin1("%1").arg(m_data[index].animationcount)); result.insert(tr("Animations"), QString::fromLatin1("%1").arg(m_data[index].animationcount));
result.insert(tr("Context"), tr(m_data[index].threadId == QmlDebug::GuiThread ? result.insert(tr("Context"), tr(selectionId(index) == QmlDebug::GuiThread ? "GUI Thread" :
"GUI Thread" : "Render Thread")); "Render Thread"));
return result; return result;
} }

View File

@@ -57,14 +57,14 @@ public:
struct QmlPaintEventData { struct QmlPaintEventData {
int framerate; int framerate;
int animationcount; int animationcount;
QmlDebug::AnimationThread threadId; int typeId;
}; };
QmlProfilerAnimationsModel(QObject *parent = 0); QmlProfilerAnimationsModel(QObject *parent = 0);
int rowMaxValue(int rowNumber) const; int rowMaxValue(int rowNumber) const;
int selectionId(int index) const; int typeId(int index) const;
int row(int index) const; int row(int index) const;
QColor color(int index) const; QColor color(int index) const;
@@ -84,7 +84,7 @@ private:
QVector<QmlProfilerAnimationsModel::QmlPaintEventData> m_data; QVector<QmlProfilerAnimationsModel::QmlPaintEventData> m_data;
int m_maxGuiThreadAnimations; int m_maxGuiThreadAnimations;
int m_maxRenderThreadAnimations; int m_maxRenderThreadAnimations;
int rowFromThreadId(QmlDebug::AnimationThread threadId) const; int rowFromThreadId(int threadId) const;
}; };
} }

View File

@@ -259,15 +259,9 @@ QVariantMap QmlProfilerRangeModel::location(int index) const
return result; return result;
} }
bool QmlProfilerRangeModel::handlesTypeId(int typeId) const int QmlProfilerRangeModel::typeId(int index) const
{ {
if (typeId < 0) return selectionId(index);
return false;
const QmlProfilerDataModel::QmlEventTypeData &type =
modelManager()->qmlModel()->getEventTypes().at(typeId);
if (type.message != message() || type.rangeType != rangeType())
return false;
return true;
} }
int QmlProfilerRangeModel::selectionIdForLocation(const QString &filename, int line, int column) const int QmlProfilerRangeModel::selectionIdForLocation(const QString &filename, int line, int column) const

View File

@@ -74,7 +74,7 @@ public:
QVariantMap details(int index) const; QVariantMap details(int index) const;
QVariantMap location(int index) const; QVariantMap location(int index) const;
bool handlesTypeId(int typeIndex) const; int typeId(int index) const;
int selectionIdForLocation(const QString &filename, int line, int column) const; int selectionIdForLocation(const QString &filename, int line, int column) const;
protected: protected: