forked from qt-creator/qt-creator
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 <ulf.hermann@qt.io>
This commit is contained in:
@@ -52,16 +52,16 @@ QString QmlProfilerStatisticsModel::nameForType(RangeType typeNumber)
|
|||||||
|
|
||||||
double QmlProfilerStatisticsModel::durationPercent(int typeId) const
|
double QmlProfilerStatisticsModel::durationPercent(int typeId) const
|
||||||
{
|
{
|
||||||
const QmlEventStats &global = m_data[-1];
|
return (typeId >= 0)
|
||||||
const QmlEventStats &stats = m_data[typeId];
|
? double(m_data[typeId].totalNonRecursive()) / double(m_rootDuration) * 100
|
||||||
return double(stats.duration - stats.durationRecursive) / double(global.duration) * 100l;
|
: 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
double QmlProfilerStatisticsModel::durationSelfPercent(int typeId) const
|
double QmlProfilerStatisticsModel::durationSelfPercent(int typeId) const
|
||||||
{
|
{
|
||||||
const QmlEventStats &global = m_data[-1];
|
return (typeId >= 0)
|
||||||
const QmlEventStats &stats = m_data[typeId];
|
? (double(m_data[typeId].self) / double(m_rootDuration) * 100)
|
||||||
return double(stats.durationSelf) / double(global.duration) * 100l;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlProfilerStatisticsModel::QmlProfilerStatisticsModel(QmlProfilerModelManager *modelManager)
|
QmlProfilerStatisticsModel::QmlProfilerStatisticsModel(QmlProfilerModelManager *modelManager)
|
||||||
@@ -122,7 +122,8 @@ bool QmlProfilerStatisticsModel::isRestrictedToRange() const
|
|||||||
return m_modelManager->isRestrictedToRange();
|
return m_modelManager->isRestrictedToRange();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QHash<int, QmlProfilerStatisticsModel::QmlEventStats> &QmlProfilerStatisticsModel::getData() const
|
const QVector<QmlProfilerStatisticsModel::QmlEventStats> &
|
||||||
|
QmlProfilerStatisticsModel::getData() const
|
||||||
{
|
{
|
||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
@@ -193,11 +194,11 @@ QString QmlProfilerStatisticsModel::summary(const QVector<int> &typeIds) const
|
|||||||
|
|
||||||
void QmlProfilerStatisticsModel::clear()
|
void QmlProfilerStatisticsModel::clear()
|
||||||
{
|
{
|
||||||
|
m_rootDuration = 0;
|
||||||
m_data.clear();
|
m_data.clear();
|
||||||
m_notes.clear();
|
m_notes.clear();
|
||||||
m_callStack.clear();
|
m_callStack.clear();
|
||||||
m_compileStack.clear();
|
m_compileStack.clear();
|
||||||
m_durations.clear();
|
|
||||||
if (!m_calleesModel.isNull())
|
if (!m_calleesModel.isNull())
|
||||||
m_calleesModel->clear();
|
m_calleesModel->clear();
|
||||||
if (!m_callersModel.isNull())
|
if (!m_callersModel.isNull())
|
||||||
@@ -256,42 +257,40 @@ void QmlProfilerStatisticsModel::loadEvent(const QmlEvent &event, const QmlEvent
|
|||||||
if (!m_acceptedTypes.contains(type.rangeType()))
|
if (!m_acceptedTypes.contains(type.rangeType()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const int typeIndex = event.typeIndex();
|
||||||
bool isRecursive = false;
|
bool isRecursive = false;
|
||||||
QStack<QmlEvent> &stack = type.rangeType() == Compiling ? m_compileStack : m_callStack;
|
QStack<QmlEvent> &stack = type.rangeType() == Compiling ? m_compileStack : m_callStack;
|
||||||
switch (event.rangeStage()) {
|
switch (event.rangeStage()) {
|
||||||
case RangeStart:
|
case RangeStart:
|
||||||
stack.push(event);
|
stack.push(event);
|
||||||
|
if (m_data.length() <= typeIndex)
|
||||||
|
m_data.resize(m_modelManager->numLoadedEventTypes());
|
||||||
break;
|
break;
|
||||||
case RangeEnd: {
|
case RangeEnd: {
|
||||||
// update stats
|
// update stats
|
||||||
QTC_ASSERT(!stack.isEmpty(), return);
|
QTC_ASSERT(!stack.isEmpty(), return);
|
||||||
QTC_ASSERT(stack.top().typeIndex() == event.typeIndex(), return);
|
QTC_ASSERT(stack.top().typeIndex() == typeIndex, return);
|
||||||
QmlEventStats *stats = &m_data[event.typeIndex()];
|
QmlEventStats &stats = m_data[typeIndex];
|
||||||
qint64 duration = event.timestamp() - stack.top().timestamp();
|
qint64 duration = event.timestamp() - stack.top().timestamp();
|
||||||
stats->duration += duration;
|
stats.total += duration;
|
||||||
stats->durationSelf += duration;
|
stats.self += duration;
|
||||||
if (duration < stats->minTime)
|
stats.durations.push_back(duration);
|
||||||
stats->minTime = duration;
|
|
||||||
if (duration > stats->maxTime)
|
|
||||||
stats->maxTime = duration;
|
|
||||||
stats->calls++;
|
|
||||||
// for median computing
|
|
||||||
m_durations[event.typeIndex()].append(duration);
|
|
||||||
stack.pop();
|
stack.pop();
|
||||||
|
|
||||||
// recursion detection: check whether event was already in stack
|
// recursion detection: check whether event was already in stack
|
||||||
for (int ii = 0; ii < stack.size(); ++ii) {
|
for (int ii = 0; ii < stack.size(); ++ii) {
|
||||||
if (stack.at(ii).typeIndex() == event.typeIndex()) {
|
if (stack.at(ii).typeIndex() == typeIndex) {
|
||||||
isRecursive = true;
|
isRecursive = true;
|
||||||
stats->durationRecursive += duration;
|
stats.recursive += duration;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stack.isEmpty())
|
if (!stack.isEmpty())
|
||||||
m_data[stack.top().typeIndex()].durationSelf -= duration;
|
m_data[stack.top().typeIndex()].self -= duration;
|
||||||
else
|
else
|
||||||
m_data[-1].duration += duration;
|
m_rootDuration += duration;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -307,20 +306,8 @@ void QmlProfilerStatisticsModel::loadEvent(const QmlEvent &event, const QmlEvent
|
|||||||
|
|
||||||
void QmlProfilerStatisticsModel::finalize()
|
void QmlProfilerStatisticsModel::finalize()
|
||||||
{
|
{
|
||||||
// post-process: calc mean time, median time, percentoftime
|
for (QmlEventStats &stats : m_data)
|
||||||
for (QHash<int, QmlEventStats>::iterator it = m_data.begin(); it != m_data.end(); ++it) {
|
stats.finalize();
|
||||||
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;
|
|
||||||
|
|
||||||
emit dataAvailable();
|
emit dataAvailable();
|
||||||
}
|
}
|
||||||
@@ -346,15 +333,15 @@ QmlProfilerStatisticsRelativesModel::QmlProfilerStatisticsRelativesModel(
|
|||||||
this, &QmlProfilerStatisticsRelativesModel::dataAvailable);
|
this, &QmlProfilerStatisticsRelativesModel::dataAvailable);
|
||||||
}
|
}
|
||||||
|
|
||||||
const QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesMap &
|
const QVector<QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesData> &
|
||||||
QmlProfilerStatisticsRelativesModel::getData(int typeId) const
|
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()) {
|
if (it != m_data.end()) {
|
||||||
return it.value();
|
return it.value();
|
||||||
} else {
|
} else {
|
||||||
static const QmlStatisticsRelativesMap emptyMap;
|
static const QVector<QmlStatisticsRelativesData> emptyVector;
|
||||||
return emptyMap;
|
return emptyVector;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,6 +350,18 @@ const QVector<QmlEventType> &QmlProfilerStatisticsRelativesModel::getTypes() con
|
|||||||
return m_modelManager->eventTypes();
|
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,
|
void QmlProfilerStatisticsRelativesModel::loadEvent(RangeType type, const QmlEvent &event,
|
||||||
bool isRecursive)
|
bool isRecursive)
|
||||||
{
|
{
|
||||||
@@ -379,15 +378,16 @@ void QmlProfilerStatisticsRelativesModel::loadEvent(RangeType type, const QmlEve
|
|||||||
int selfTypeIndex = (m_relation == QmlProfilerStatisticsCallers) ? event.typeIndex() :
|
int selfTypeIndex = (m_relation == QmlProfilerStatisticsCallers) ? event.typeIndex() :
|
||||||
callerTypeIndex;
|
callerTypeIndex;
|
||||||
|
|
||||||
QmlStatisticsRelativesMap &relativesMap = m_data[selfTypeIndex];
|
QVector<QmlStatisticsRelativesData> &relatives = m_data[selfTypeIndex];
|
||||||
QmlStatisticsRelativesMap::Iterator it = relativesMap.find(relativeTypeIndex);
|
auto it = std::lower_bound(relatives.begin(), relatives.end(), relativeTypeIndex);
|
||||||
if (it != relativesMap.end()) {
|
if (it != relatives.end() && it->typeIndex == relativeTypeIndex) {
|
||||||
it->calls++;
|
it->calls++;
|
||||||
it->duration += event.timestamp() - stack.top().startTime;
|
it->duration += event.timestamp() - stack.top().startTime;
|
||||||
it->isRecursive = isRecursive || it->isRecursive;
|
it->isRecursive = isRecursive || it->isRecursive;
|
||||||
} else {
|
} else {
|
||||||
relativesMap.insert(relativeTypeIndex, QmlStatisticsRelativesData(
|
relatives.insert(it, QmlStatisticsRelativesData(
|
||||||
event.timestamp() - stack.top().startTime, 1, isRecursive));
|
event.timestamp() - stack.top().startTime, 1, relativeTypeIndex,
|
||||||
|
isRecursive));
|
||||||
}
|
}
|
||||||
stack.pop();
|
stack.pop();
|
||||||
break;
|
break;
|
||||||
|
@@ -30,6 +30,8 @@
|
|||||||
#include "qmleventlocation.h"
|
#include "qmleventlocation.h"
|
||||||
#include "qmlprofilerconstants.h"
|
#include "qmlprofilerconstants.h"
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QStack>
|
#include <QStack>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
@@ -52,13 +54,46 @@ public:
|
|||||||
static QString nameForType(RangeType typeNumber);
|
static QString nameForType(RangeType typeNumber);
|
||||||
|
|
||||||
struct QmlEventStats {
|
struct QmlEventStats {
|
||||||
qint64 duration = 0;
|
std::vector<qint64> durations;
|
||||||
qint64 durationSelf = 0;
|
qint64 total = 0;
|
||||||
qint64 durationRecursive = 0;
|
qint64 self = 0;
|
||||||
|
qint64 recursive = 0;
|
||||||
|
qint64 minimum = 0;
|
||||||
|
qint64 maximum = 0;
|
||||||
|
qint64 median = 0;
|
||||||
qint64 calls = 0;
|
qint64 calls = 0;
|
||||||
qint64 minTime = std::numeric_limits<qint64>::max();
|
|
||||||
qint64 maxTime = 0;
|
void finalize()
|
||||||
qint64 medianTime = 0;
|
{
|
||||||
|
static const qint64 qint64Max = std::numeric_limits<qint64>::max();
|
||||||
|
size_t size = durations.size();
|
||||||
|
QTC_ASSERT(size <= qint64Max, size = qint64Max);
|
||||||
|
calls = static_cast<qint64>(size);
|
||||||
|
|
||||||
|
if (size == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::sort(durations.begin(), durations.end());
|
||||||
|
const auto avg
|
||||||
|
= [](const qint64 a, const qint64 b) { return a / 2ll + b / 2ll + ((a & 1) + (b & 1)) / 2ll; };
|
||||||
|
|
||||||
|
const size_t half = size / 2;
|
||||||
|
median = (size & 1) == 0 ? avg(durations[half - 1], durations[half]) : durations[half];
|
||||||
|
minimum = durations.front();
|
||||||
|
maximum = durations.back();
|
||||||
|
|
||||||
|
durations.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 average() const
|
||||||
|
{
|
||||||
|
return calls == 0 ? 0 : total / calls;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 totalNonRecursive() const
|
||||||
|
{
|
||||||
|
return total - recursive;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
double durationPercent(int typeId) const;
|
double durationPercent(int typeId) const;
|
||||||
@@ -72,9 +107,10 @@ public:
|
|||||||
|
|
||||||
QStringList details(int typeIndex) const;
|
QStringList details(int typeIndex) const;
|
||||||
QString summary(const QVector<int> &typeIds) const;
|
QString summary(const QVector<int> &typeIds) const;
|
||||||
const QHash<int, QmlEventStats> &getData() const;
|
const QVector<QmlEventStats> &getData() const;
|
||||||
const QVector<QmlEventType> &getTypes() const;
|
const QVector<QmlEventType> &getTypes() const;
|
||||||
const QHash<int, QString> &getNotes() const;
|
const QHash<int, QString> &getNotes() const;
|
||||||
|
qint64 rootDuration() const { return m_rootDuration; }
|
||||||
|
|
||||||
int count() const;
|
int count() const;
|
||||||
void clear();
|
void clear();
|
||||||
@@ -93,7 +129,7 @@ private:
|
|||||||
void dataChanged();
|
void dataChanged();
|
||||||
void notesChanged(int typeIndex);
|
void notesChanged(int typeIndex);
|
||||||
|
|
||||||
QHash<int, QmlEventStats> m_data;
|
QVector<QmlEventStats> m_data;
|
||||||
|
|
||||||
QPointer<QmlProfilerStatisticsRelativesModel> m_calleesModel;
|
QPointer<QmlProfilerStatisticsRelativesModel> m_calleesModel;
|
||||||
QPointer<QmlProfilerStatisticsRelativesModel> m_callersModel;
|
QPointer<QmlProfilerStatisticsRelativesModel> m_callersModel;
|
||||||
@@ -104,7 +140,8 @@ private:
|
|||||||
|
|
||||||
QStack<QmlEvent> m_callStack;
|
QStack<QmlEvent> m_callStack;
|
||||||
QStack<QmlEvent> m_compileStack;
|
QStack<QmlEvent> m_compileStack;
|
||||||
QHash<int, QVector<qint64>> m_durations;
|
|
||||||
|
qint64 m_rootDuration = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QmlProfilerStatisticsRelativesModel : public QObject
|
class QmlProfilerStatisticsRelativesModel : public QObject
|
||||||
@@ -113,13 +150,14 @@ class QmlProfilerStatisticsRelativesModel : public QObject
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
struct QmlStatisticsRelativesData {
|
struct QmlStatisticsRelativesData {
|
||||||
QmlStatisticsRelativesData(qint64 duration = 0, qint64 calls = 0, bool isRecursive = false)
|
QmlStatisticsRelativesData(qint64 duration = 0, qint64 calls = 0, int typeIndex = -1,
|
||||||
: duration(duration), calls(calls), isRecursive(isRecursive) {}
|
bool isRecursive = false)
|
||||||
|
: duration(duration), calls(calls), typeIndex(typeIndex), isRecursive(isRecursive) {}
|
||||||
qint64 duration;
|
qint64 duration;
|
||||||
qint64 calls;
|
qint64 calls;
|
||||||
|
int typeIndex;
|
||||||
bool isRecursive;
|
bool isRecursive;
|
||||||
};
|
};
|
||||||
typedef QHash <int, QmlStatisticsRelativesData> QmlStatisticsRelativesMap;
|
|
||||||
|
|
||||||
QmlProfilerStatisticsRelativesModel(QmlProfilerModelManager *modelManager,
|
QmlProfilerStatisticsRelativesModel(QmlProfilerModelManager *modelManager,
|
||||||
QmlProfilerStatisticsModel *statisticsModel,
|
QmlProfilerStatisticsModel *statisticsModel,
|
||||||
@@ -128,7 +166,7 @@ public:
|
|||||||
int count() const;
|
int count() const;
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
const QmlStatisticsRelativesMap &getData(int typeId) const;
|
const QVector<QmlStatisticsRelativesData> &getData(int typeId) const;
|
||||||
const QVector<QmlEventType> &getTypes() const;
|
const QVector<QmlEventType> &getTypes() const;
|
||||||
|
|
||||||
void loadEvent(RangeType type, const QmlEvent &event, bool isRecursive);
|
void loadEvent(RangeType type, const QmlEvent &event, bool isRecursive);
|
||||||
@@ -139,7 +177,7 @@ signals:
|
|||||||
void dataAvailable();
|
void dataAvailable();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QHash<int, QmlStatisticsRelativesMap> m_data;
|
QHash<int, QVector<QmlStatisticsRelativesData>> m_data;
|
||||||
QPointer<QmlProfilerModelManager> m_modelManager;
|
QPointer<QmlProfilerModelManager> m_modelManager;
|
||||||
|
|
||||||
struct Frame {
|
struct Frame {
|
||||||
|
@@ -418,13 +418,13 @@ void QmlProfilerStatisticsMainView::buildModel()
|
|||||||
|
|
||||||
void QmlProfilerStatisticsMainView::updateNotes(int typeIndex)
|
void QmlProfilerStatisticsMainView::updateNotes(int typeIndex)
|
||||||
{
|
{
|
||||||
const QHash<int, QmlProfilerStatisticsModel::QmlEventStats> &eventList = m_model->getData();
|
const QVector<QmlProfilerStatisticsModel::QmlEventStats> &eventList = m_model->getData();
|
||||||
const QHash<int, QString> ¬eList = m_model->getNotes();
|
const QHash<int, QString> ¬eList = m_model->getNotes();
|
||||||
QStandardItem *rootItem = m_standardItemModel->invisibleRootItem();
|
QStandardItem *rootItem = m_standardItemModel->invisibleRootItem();
|
||||||
|
|
||||||
for (int rowIndex = 0; rowIndex < rootItem->rowCount(); ++rowIndex) {
|
for (int rowIndex = 0; rowIndex < rootItem->rowCount(); ++rowIndex) {
|
||||||
int rowType = rootItem->child(rowIndex)->data(TypeIdRole).toInt();
|
int rowType = rootItem->child(rowIndex)->data(TypeIdRole).toInt();
|
||||||
if (rowType != typeIndex && typeIndex != -1)
|
if (rowType == -1 || (rowType != typeIndex && typeIndex != -1))
|
||||||
continue;
|
continue;
|
||||||
const QmlProfilerStatisticsModel::QmlEventStats &stats = eventList[rowType];
|
const QmlProfilerStatisticsModel::QmlEventStats &stats = eventList[rowType];
|
||||||
|
|
||||||
@@ -434,10 +434,10 @@ void QmlProfilerStatisticsMainView::updateNotes(int typeIndex)
|
|||||||
if (it != noteList.end()) {
|
if (it != noteList.end()) {
|
||||||
item->setBackground(colors()->noteBackground);
|
item->setBackground(colors()->noteBackground);
|
||||||
item->setToolTip(it.value());
|
item->setToolTip(it.value());
|
||||||
} else if (stats.durationRecursive > 0) {
|
} else if (stats.recursive > 0) {
|
||||||
item->setBackground(colors()->noteBackground);
|
item->setBackground(colors()->noteBackground);
|
||||||
item->setToolTip(tr("+%1 in recursive calls")
|
item->setToolTip(tr("+%1 in recursive calls")
|
||||||
.arg(Timeline::formatTime(stats.durationRecursive)));
|
.arg(Timeline::formatTime(stats.recursive)));
|
||||||
} else if (!item->toolTip().isEmpty()){
|
} else if (!item->toolTip().isEmpty()){
|
||||||
item->setBackground(colors()->defaultBackground);
|
item->setBackground(colors()->defaultBackground);
|
||||||
item->setToolTip(QString());
|
item->setToolTip(QString());
|
||||||
@@ -468,14 +468,21 @@ QStringList QmlProfilerStatisticsMainView::details(int typeId) const
|
|||||||
|
|
||||||
void QmlProfilerStatisticsMainView::parseModel()
|
void QmlProfilerStatisticsMainView::parseModel()
|
||||||
{
|
{
|
||||||
const QHash<int, QmlProfilerStatisticsModel::QmlEventStats> &eventList = m_model->getData();
|
const QVector<QmlProfilerStatisticsModel::QmlEventStats> &eventList = m_model->getData();
|
||||||
const QVector<QmlEventType> &typeList = m_model->getTypes();
|
const QVector<QmlEventType> &typeList = m_model->getTypes();
|
||||||
|
|
||||||
QHash<int, QmlProfilerStatisticsModel::QmlEventStats>::ConstIterator it;
|
QmlProfilerStatisticsModel::QmlEventStats rootEventStats;
|
||||||
for (it = eventList.constBegin(); it != eventList.constEnd(); ++it) {
|
rootEventStats.total = rootEventStats.maximum = rootEventStats.minimum = rootEventStats.median
|
||||||
int typeIndex = it.key();
|
= m_model->rootDuration();
|
||||||
const QmlProfilerStatisticsModel::QmlEventStats &stats = it.value();
|
rootEventStats.calls = rootEventStats.total > 0 ? 1 : 0;
|
||||||
const QmlEventType &type = (typeIndex != -1 ? typeList[typeIndex] : *rootEventType());
|
|
||||||
|
for (int typeIndex = -1; typeIndex < eventList.size(); ++typeIndex) {
|
||||||
|
const QmlProfilerStatisticsModel::QmlEventStats &stats = typeIndex >= 0
|
||||||
|
? eventList[typeIndex] : rootEventStats;
|
||||||
|
if (stats.calls == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const QmlEventType &type = typeIndex >= 0 ? typeList[typeIndex] : *rootEventType();
|
||||||
QStandardItem *rootItem = m_standardItemModel->invisibleRootItem();
|
QStandardItem *rootItem = m_standardItemModel->invisibleRootItem();
|
||||||
QList<QStandardItem *> newRow;
|
QList<QStandardItem *> newRow;
|
||||||
|
|
||||||
@@ -491,30 +498,30 @@ void QmlProfilerStatisticsMainView::parseModel()
|
|||||||
+ QLatin1String(" %"), percent);
|
+ QLatin1String(" %"), percent);
|
||||||
|
|
||||||
newRow << new StatisticsViewItem(
|
newRow << new StatisticsViewItem(
|
||||||
Timeline::formatTime(stats.duration - stats.durationRecursive),
|
Timeline::formatTime(stats.totalNonRecursive()),
|
||||||
stats.duration - stats.durationRecursive);
|
stats.totalNonRecursive());
|
||||||
|
|
||||||
const double percentSelf = m_model->durationSelfPercent(typeIndex);
|
const double percentSelf = m_model->durationSelfPercent(typeIndex);
|
||||||
newRow << new StatisticsViewItem(QString::number(percentSelf, 'f', 2)
|
newRow << new StatisticsViewItem(QString::number(percentSelf, 'f', 2)
|
||||||
+ QLatin1String(" %"), percentSelf);
|
+ QLatin1String(" %"), percentSelf);
|
||||||
|
|
||||||
newRow << new StatisticsViewItem(Timeline::formatTime(stats.durationSelf),
|
newRow << new StatisticsViewItem(Timeline::formatTime(stats.self),
|
||||||
stats.durationSelf);
|
stats.self);
|
||||||
|
|
||||||
newRow << new StatisticsViewItem(QString::number(stats.calls), stats.calls);
|
newRow << new StatisticsViewItem(QString::number(stats.calls), stats.calls);
|
||||||
|
|
||||||
const qint64 timePerCall = stats.calls > 0 ? stats.duration / stats.calls : 0;
|
const qint64 timePerCall = stats.average();
|
||||||
newRow << new StatisticsViewItem(Timeline::formatTime(timePerCall),
|
newRow << new StatisticsViewItem(Timeline::formatTime(timePerCall),
|
||||||
timePerCall);
|
timePerCall);
|
||||||
|
|
||||||
newRow << new StatisticsViewItem(Timeline::formatTime(stats.medianTime),
|
newRow << new StatisticsViewItem(Timeline::formatTime(stats.median),
|
||||||
stats.medianTime);
|
stats.median);
|
||||||
|
|
||||||
newRow << new StatisticsViewItem(Timeline::formatTime(stats.maxTime),
|
newRow << new StatisticsViewItem(Timeline::formatTime(stats.maximum),
|
||||||
stats.maxTime);
|
stats.maximum);
|
||||||
|
|
||||||
newRow << new StatisticsViewItem(Timeline::formatTime(stats.minTime),
|
newRow << new StatisticsViewItem(Timeline::formatTime(stats.minimum),
|
||||||
stats.minTime);
|
stats.minimum);
|
||||||
|
|
||||||
newRow << new StatisticsViewItem(type.data().isEmpty() ? tr("Source code not available")
|
newRow << new StatisticsViewItem(type.data().isEmpty() ? tr("Source code not available")
|
||||||
: type.data(), type.data());
|
: type.data(), type.data());
|
||||||
@@ -682,7 +689,7 @@ void QmlProfilerStatisticsRelativesView::displayType(int typeIndex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerStatisticsRelativesView::rebuildTree(
|
void QmlProfilerStatisticsRelativesView::rebuildTree(
|
||||||
const QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesMap &map)
|
const QVector<QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesData> &data)
|
||||||
{
|
{
|
||||||
Q_ASSERT(treeModel());
|
Q_ASSERT(treeModel());
|
||||||
treeModel()->clear();
|
treeModel()->clear();
|
||||||
@@ -690,11 +697,10 @@ void QmlProfilerStatisticsRelativesView::rebuildTree(
|
|||||||
QStandardItem *topLevelItem = treeModel()->invisibleRootItem();
|
QStandardItem *topLevelItem = treeModel()->invisibleRootItem();
|
||||||
const QVector<QmlEventType> &typeList = m_model->getTypes();
|
const QVector<QmlEventType> &typeList = m_model->getTypes();
|
||||||
|
|
||||||
QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesMap::const_iterator it;
|
for (auto it = data.constBegin(); it != data.constEnd(); ++it) {
|
||||||
for (it = map.constBegin(); it != map.constEnd(); ++it) {
|
const QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesData &stats = *it;
|
||||||
const QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesData &stats = it.value();
|
const QmlEventType &type = stats.typeIndex != -1 ? typeList[stats.typeIndex]
|
||||||
int typeIndex = it.key();
|
: *rootEventType();
|
||||||
const QmlEventType &type = (typeIndex != -1 ? typeList[typeIndex] : *rootEventType());
|
|
||||||
QList<QStandardItem *> newRow;
|
QList<QStandardItem *> newRow;
|
||||||
|
|
||||||
// ToDo: here we were going to search for the data in the other model
|
// ToDo: here we were going to search for the data in the other model
|
||||||
@@ -712,7 +718,7 @@ void QmlProfilerStatisticsRelativesView::rebuildTree(
|
|||||||
type.data(), type.data());
|
type.data(), type.data());
|
||||||
|
|
||||||
QStandardItem *first = newRow.at(RelativeLocation);
|
QStandardItem *first = newRow.at(RelativeLocation);
|
||||||
first->setData(typeIndex, TypeIdRole);
|
first->setData(stats.typeIndex, TypeIdRole);
|
||||||
const QmlEventLocation location(type.location());
|
const QmlEventLocation location(type.location());
|
||||||
first->setData(location.filename(), FilenameRole);
|
first->setData(location.filename(), FilenameRole);
|
||||||
first->setData(location.line(), LineRole);
|
first->setData(location.line(), LineRole);
|
||||||
|
@@ -166,7 +166,8 @@ signals:
|
|||||||
void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber);
|
void gotoSourceLocation(const QString &fileName, int lineNumber, int columnNumber);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void rebuildTree(const QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesMap &map);
|
void rebuildTree(
|
||||||
|
const QVector<QmlProfilerStatisticsRelativesModel::QmlStatisticsRelativesData> &data);
|
||||||
void updateHeader();
|
void updateHeader();
|
||||||
QStandardItemModel *treeModel();
|
QStandardItemModel *treeModel();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user