Commit 307d45ec authored by Ulf Hermann's avatar Ulf Hermann Committed by Ulf Hermann
Browse files

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: default avatarLeena Miettinen <riitta-leena.miettinen@theqtcompany.com>
Reviewed-by: default avatarKai Koehne <kai.koehne@theqtcompany.com>
parent 4ec75995
......@@ -304,10 +304,15 @@ qint64 AbstractTimelineModel::endTime(int index) const
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
{
Q_D(const AbstractTimelineModel);
return d->ranges[index].typeId;
Q_UNUSED(index)
return -1;
}
/*!
......@@ -374,10 +379,17 @@ QVariantMap AbstractTimelineModel::location(int index) const
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
{
Q_UNUSED(typeIndex);
return false;
if (typeIndex < 0)
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
......@@ -453,16 +465,17 @@ QColor AbstractTimelineModel::colorByHue(int hue) const
}
/*!
\fn int AbstractTimelineModel::insert(qint64 startTime, qint64 duration)
Inserts a range at the given time position and returns its index.
Inserts an event at the time specified by \a startTime with the given \a duration and returns
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);
/* 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. */
int index = d->insertSorted(d->ranges,
AbstractTimelineModelPrivate::Range(startTime, duration, typeId));
AbstractTimelineModelPrivate::Range(startTime, duration, selectionId));
if (index < d->ranges.size() - 1)
d->incrementStartIndices(index);
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 the given data as range start at the given time position and
returns its index. The range end is not set.
Inserts a range start at the time given by \a startTime and returns its index. The range end is
not set. The \a selectionId determines the selection group the new event belongs to.
\sa selectionId()
*/
int AbstractTimelineModel::insertStart(qint64 startTime, int typeId)
int AbstractTimelineModel::insertStart(qint64 startTime, int selectionId)
{
Q_D(AbstractTimelineModel);
int index = d->insertSorted(d->ranges,
AbstractTimelineModelPrivate::Range(startTime, 0, typeId));
AbstractTimelineModelPrivate::Range(startTime, 0, selectionId));
if (index < d->ranges.size() - 1)
d->incrementStartIndices(index);
return index;
......@@ -567,10 +580,18 @@ int AbstractTimelineModel::rowCount() const
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
{
Q_D(const AbstractTimelineModel);
return d->ranges[index].typeId;
return d->ranges[index].selectionId;
}
void AbstractTimelineModel::clear()
......
......@@ -73,13 +73,12 @@ public:
qint64 duration(int index) const;
qint64 startTime(int index) const;
qint64 endTime(int index) const;
int typeId(int index) const;
int selectionId(int index) const;
int firstIndex(qint64 startTime) const;
int firstIndexNoParents(qint64 startTime) const;
int lastIndex(qint64 endTime) const;
bool accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const;
bool expanded() const;
bool hidden() const;
void setExpanded(bool expanded);
......@@ -97,8 +96,9 @@ public:
// Methods which can optionally be implemented by child models.
// returned map should contain "file", "line", "column" properties, or be empty
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 accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const;
virtual int selectionIdForLocation(const QString &filename, int line, int column) const;
virtual int bindingLoopDest(int index) const;
virtual float relativeHeight(int index) const;
......@@ -120,8 +120,8 @@ protected:
QColor colorByFraction(double fraction) const;
QColor colorByHue(int hue) const;
int insert(qint64 startTime, qint64 duration, int typeId);
int insertStart(qint64 startTime, int typeId);
int insert(qint64 startTime, qint64 duration, int selectionId);
int insertStart(qint64 startTime, int selectionId);
void insertEnd(int index, qint64 duration);
void computeNesting();
......
......@@ -48,12 +48,12 @@ public:
};
struct Range {
Range() : start(-1), duration(-1), typeId(-1), parent(-1) {}
Range(qint64 start, qint64 duration, int typeId) :
start(start), duration(duration), typeId(typeId), parent(-1) {}
Range() : start(-1), duration(-1), selectionId(-1), parent(-1) {}
Range(qint64 start, qint64 duration, int selectionId) :
start(start), duration(duration), selectionId(selectionId), parent(-1) {}
qint64 start;
qint64 duration;
int typeId;
int selectionId;
int parent;
inline qint64 timestamp() const {return start;}
};
......
......@@ -82,6 +82,7 @@ void QmlProfilerAnimationsModel::loadData()
const QVector<QmlProfilerDataModel::QmlEventData> &referenceList = simpleModel->getEvents();
const QVector<QmlProfilerDataModel::QmlEventTypeData> &typeList = simpleModel->getEventTypes();
QmlDebug::AnimationThread lastThread;
QmlPaintEventData lastEvent;
qint64 minNextStartTimes[] = {0, 0};
......@@ -90,7 +91,7 @@ void QmlProfilerAnimationsModel::loadData()
if (!accepted(type))
continue;
lastEvent.threadId = (QmlDebug::AnimationThread)event.numericData3;
lastThread = (QmlDebug::AnimationThread)event.numericData3;
// initial estimation of the event duration: 1/framerate
qint64 estimatedDuration = event.numericData1 > 0 ? 1e9/event.numericData1 : 1;
......@@ -99,7 +100,7 @@ void QmlProfilerAnimationsModel::loadData()
qint64 realEndTime = event.startTime;
// 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
if (realStartTime >= realEndTime)
......@@ -107,18 +108,19 @@ void QmlProfilerAnimationsModel::loadData()
// 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.
lastEvent.typeId = event.typeIndex;
lastEvent.framerate = (int)event.numericData1;
lastEvent.animationcount = (int)event.numericData2;
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);
else
m_maxRenderThreadAnimations = qMax(lastEvent.animationcount, m_maxRenderThreadAnimations);
minNextStartTimes[lastEvent.threadId] = event.startTime + 1;
minNextStartTimes[lastThread] = event.startTime + 1;
updateProgress(count(), referenceList.count());
}
......@@ -131,14 +133,14 @@ void QmlProfilerAnimationsModel::loadData()
/////////////////// QML interface
int QmlProfilerAnimationsModel::rowFromThreadId(QmlDebug::AnimationThread threadId) const
int QmlProfilerAnimationsModel::rowFromThreadId(int threadId) const
{
return (threadId == QmlDebug::GuiThread || m_maxGuiThreadAnimations == 0) ? 1 : 2;
}
int QmlProfilerAnimationsModel::row(int index) const
{
return rowFromThreadId(m_data[index].threadId);
return rowFromThreadId(selectionId(index));
}
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
......@@ -170,16 +172,16 @@ QColor QmlProfilerAnimationsModel::color(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.
// 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;
return boost + (1.0 - boost) * (float)data.animationcount /
(float)(data.threadId == QmlDebug::GuiThread ? m_maxGuiThreadAnimations :
m_maxRenderThreadAnimations);
return boost + (1.0 - boost) * (float)m_data[index].animationcount /
(float)(thread == QmlDebug::GuiThread ? m_maxGuiThreadAnimations :
m_maxRenderThreadAnimations);
}
QVariantList QmlProfilerAnimationsModel::labels() const
......@@ -213,8 +215,8 @@ QVariantMap QmlProfilerAnimationsModel::details(int index) const
result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(duration(index)));
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("Context"), tr(m_data[index].threadId == QmlDebug::GuiThread ?
"GUI Thread" : "Render Thread"));
result.insert(tr("Context"), tr(selectionId(index) == QmlDebug::GuiThread ? "GUI Thread" :
"Render Thread"));
return result;
}
......
......@@ -57,14 +57,14 @@ public:
struct QmlPaintEventData {
int framerate;
int animationcount;
QmlDebug::AnimationThread threadId;
int typeId;
};
QmlProfilerAnimationsModel(QObject *parent = 0);
int rowMaxValue(int rowNumber) const;
int selectionId(int index) const;
int typeId(int index) const;
int row(int index) const;
QColor color(int index) const;
......@@ -84,7 +84,7 @@ private:
QVector<QmlProfilerAnimationsModel::QmlPaintEventData> m_data;
int m_maxGuiThreadAnimations;
int m_maxRenderThreadAnimations;
int rowFromThreadId(QmlDebug::AnimationThread threadId) const;
int rowFromThreadId(int threadId) const;
};
}
......
......@@ -259,15 +259,9 @@ QVariantMap QmlProfilerRangeModel::location(int index) const
return result;
}
bool QmlProfilerRangeModel::handlesTypeId(int typeId) const
int QmlProfilerRangeModel::typeId(int index) const
{
if (typeId < 0)
return false;
const QmlProfilerDataModel::QmlEventTypeData &type =
modelManager()->qmlModel()->getEventTypes().at(typeId);
if (type.message != message() || type.rangeType != rangeType())
return false;
return true;
return selectionId(index);
}
int QmlProfilerRangeModel::selectionIdForLocation(const QString &filename, int line, int column) const
......
......@@ -74,7 +74,7 @@ public:
QVariantMap details(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;
protected:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment