aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp
diff options
context:
space:
mode:
authorUlf Hermann <[email protected]>2018-03-23 10:56:31 +0100
committerUlf Hermann <[email protected]>2018-04-16 07:16:35 +0000
commit87c12c4e1b762f890602ea603acc92bda1909e94 (patch)
tree2d5ed9b412c437c3c939b052ae6ec4516a231c4e /src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp
parent5784fce2449485b627327f88f96301298987941f (diff)
QmlProfiler: Store statistics data in a saner way
We don't need to retain the durations after finalize(), and we can use vectors instead of hashes, as we will cover almost all types anyway. Vectors allow us to potentially use the position of an item in the data as its row. Change-Id: I2c09406f0e0a42f5f517f8444755b1664efb8f3b Reviewed-by: Ulf Hermann <[email protected]>
Diffstat (limited to 'src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp')
-rw-r--r--src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp92
1 files changed, 46 insertions, 46 deletions
diff --git a/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp b/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp
index f4b9c931fae..a28647cbd0f 100644
--- a/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerstatisticsmodel.cpp
@@ -52,16 +52,16 @@ QString QmlProfilerStatisticsModel::nameForType(RangeType typeNumber)
double QmlProfilerStatisticsModel::durationPercent(int typeId) const
{
- const QmlEventStats &global = m_data[-1];
- const QmlEventStats &stats = m_data[typeId];
- return double(stats.duration - stats.durationRecursive) / double(global.duration) * 100l;
+ return (typeId >= 0)
+ ? double(m_data[typeId].totalNonRecursive()) / double(m_rootDuration) * 100
+ : 100;
}
double QmlProfilerStatisticsModel::durationSelfPercent(int typeId) const
{
- const QmlEventStats &global = m_data[-1];
- const QmlEventStats &stats = m_data[typeId];
- return double(stats.durationSelf) / double(global.duration) * 100l;
+ return (typeId >= 0)
+ ? (double(m_data[typeId].self) / double(m_rootDuration) * 100)
+ : 0;
}
QmlProfilerStatisticsModel::QmlProfilerStatisticsModel(QmlProfilerModelManager *modelManager)
@@ -122,7 +122,8 @@ bool QmlProfilerStatisticsModel::isRestrictedToRange() const
return m_modelManager->isRestrictedToRange();
}
-const QHash<int, QmlProfilerStatisticsModel::QmlEventStats> &QmlProfilerStatisticsModel::getData() const
+const QVector<QmlProfilerStatisticsModel::QmlEventStats> &
+QmlProfilerStatisticsModel::getData() const
{
return m_data;
}
@@ -193,11 +194,11 @@ QString QmlProfilerStatisticsModel::summary(const QVector<int> &typeIds) const
void QmlProfilerStatisticsModel::clear()
{
+ m_rootDuration = 0;
m_data.clear();
m_notes.clear();
m_callStack.clear();
m_compileStack.clear();
- m_durations.clear();
if (!m_calleesModel.isNull())
m_calleesModel->clear();
if (!m_callersModel.isNull())
@@ -256,42 +257,40 @@ void QmlProfilerStatisticsModel::loadEvent(const QmlEvent &event, const QmlEvent
if (!m_acceptedTypes.contains(type.rangeType()))
return;
+ const int typeIndex = event.typeIndex();
bool isRecursive = false;
QStack<QmlEvent> &stack = type.rangeType() == Compiling ? m_compileStack : m_callStack;
switch (event.rangeStage()) {
case RangeStart:
stack.push(event);
+ if (m_data.length() <= typeIndex)
+ m_data.resize(m_modelManager->numLoadedEventTypes());
break;
case RangeEnd: {
// update stats
QTC_ASSERT(!stack.isEmpty(), return);
- QTC_ASSERT(stack.top().typeIndex() == event.typeIndex(), return);
- QmlEventStats *stats = &m_data[event.typeIndex()];
+ QTC_ASSERT(stack.top().typeIndex() == typeIndex, return);
+ QmlEventStats &stats = m_data[typeIndex];
qint64 duration = event.timestamp() - stack.top().timestamp();
- stats->duration += duration;
- stats->durationSelf += duration;
- if (duration < stats->minTime)
- stats->minTime = duration;
- if (duration > stats->maxTime)
- stats->maxTime = duration;
- stats->calls++;
- // for median computing
- m_durations[event.typeIndex()].append(duration);
+ stats.total += duration;
+ stats.self += duration;
+ stats.durations.push_back(duration);
stack.pop();
// recursion detection: check whether event was already in stack
for (int ii = 0; ii < stack.size(); ++ii) {
- if (stack.at(ii).typeIndex() == event.typeIndex()) {
+ if (stack.at(ii).typeIndex() == typeIndex) {
isRecursive = true;
- stats->durationRecursive += duration;
+ stats.recursive += duration;
break;
}
}
if (!stack.isEmpty())
- m_data[stack.top().typeIndex()].durationSelf -= duration;
+ m_data[stack.top().typeIndex()].self -= duration;
else
- m_data[-1].duration += duration;
+ m_rootDuration += duration;
+
break;
}
default:
@@ -307,20 +306,8 @@ void QmlProfilerStatisticsModel::loadEvent(const QmlEvent &event, const QmlEvent
void QmlProfilerStatisticsModel::finalize()
{
- // post-process: calc mean time, median time, percentoftime
- for (QHash<int, QmlEventStats>::iterator it = m_data.begin(); it != m_data.end(); ++it) {
- QVector<qint64> eventDurations = m_durations[it.key()];
- if (!eventDurations.isEmpty()) {
- Utils::sort(eventDurations);
- it->medianTime = eventDurations.at(eventDurations.count()/2);
- }
- }
-
- // insert root event
- QmlEventStats &rootEvent = m_data[-1];
- rootEvent.minTime = rootEvent.maxTime = rootEvent.medianTime = rootEvent.duration;
- rootEvent.durationSelf = 0;
- rootEvent.calls = 1;
+ for (QmlEventStats &stats : m_data)
+ stats.finalize();
emit dataAvailable();
}
@@ -346,15 +333,15 @@ QmlProfilerStatisticsRelativesModel::QmlProfilerStatisticsRelativesModel(
this, &QmlProfilerStatisticsRelativesModel::dataAvailable);
}
-const QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesMap &
+const QVector<QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesData> &
QmlProfilerStatisticsRelativesModel::getData(int typeId) const
{
- QHash <int, QmlStatisticsRelativesMap>::ConstIterator it = m_data.find(typeId);
+ auto it = m_data.find(typeId);
if (it != m_data.end()) {
return it.value();
} else {
- static const QmlStatisticsRelativesMap emptyMap;
- return emptyMap;
+ static const QVector<QmlStatisticsRelativesData> emptyVector;
+ return emptyVector;
}
}
@@ -363,6 +350,18 @@ const QVector<QmlEventType> &QmlProfilerStatisticsRelativesModel::getTypes() con
return m_modelManager->eventTypes();
}
+bool operator<(const QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesData &a,
+ const QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesData &b)
+{
+ return a.typeIndex < b.typeIndex;
+}
+
+bool operator<(const QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesData &a,
+ int typeIndex)
+{
+ return a.typeIndex < typeIndex;
+}
+
void QmlProfilerStatisticsRelativesModel::loadEvent(RangeType type, const QmlEvent &event,
bool isRecursive)
{
@@ -379,15 +378,16 @@ void QmlProfilerStatisticsRelativesModel::loadEvent(RangeType type, const QmlEve
int selfTypeIndex = (m_relation == QmlProfilerStatisticsCallers) ? event.typeIndex() :
callerTypeIndex;
- QmlStatisticsRelativesMap &relativesMap = m_data[selfTypeIndex];
- QmlStatisticsRelativesMap::Iterator it = relativesMap.find(relativeTypeIndex);
- if (it != relativesMap.end()) {
+ QVector<QmlStatisticsRelativesData> &relatives = m_data[selfTypeIndex];
+ auto it = std::lower_bound(relatives.begin(), relatives.end(), relativeTypeIndex);
+ if (it != relatives.end() && it->typeIndex == relativeTypeIndex) {
it->calls++;
it->duration += event.timestamp() - stack.top().startTime;
it->isRecursive = isRecursive || it->isRecursive;
} else {
- relativesMap.insert(relativeTypeIndex, QmlStatisticsRelativesData(
- event.timestamp() - stack.top().startTime, 1, isRecursive));
+ relatives.insert(it, QmlStatisticsRelativesData(
+ event.timestamp() - stack.top().startTime, 1, relativeTypeIndex,
+ isRecursive));
}
stack.pop();
break;