forked from qt-creator/qt-creator
Be more verbose about aggregated memory allocations
The memory profiler aggregates allocations originating from the same QML/JS constructs into one event. This change makes sure the origins are really the same calls, not only the same functions and gives some more details on hom much memory was allocated or deallocated in how many steps. Change-Id: I784c521855122f7b3b894417de0afb216766e2d4 Reviewed-by: Kai Koehne <kai.koehne@digia.com>
This commit is contained in:
@@ -145,7 +145,7 @@ const QVariantList MemoryUsageModel::getEventDetails(int index) const
|
|||||||
const MemoryUsageModelPrivate::Range *ev = &d->range(index);
|
const MemoryUsageModelPrivate::Range *ev = &d->range(index);
|
||||||
|
|
||||||
QVariantMap res;
|
QVariantMap res;
|
||||||
if (ev->delta > 0)
|
if (ev->allocated >= -ev->deallocated)
|
||||||
res.insert(title, tr("Memory Allocated"));
|
res.insert(title, tr("Memory Allocated"));
|
||||||
else
|
else
|
||||||
res.insert(title, tr("Memory Freed"));
|
res.insert(title, tr("Memory Freed"));
|
||||||
@@ -156,7 +156,14 @@ const QVariantList MemoryUsageModel::getEventDetails(int index) const
|
|||||||
result << res;
|
result << res;
|
||||||
res.clear();
|
res.clear();
|
||||||
|
|
||||||
res.insert(tr("Allocation"), QVariant(QString::fromLatin1("%1 bytes").arg(ev->delta)));
|
if (ev->allocations > 0) {
|
||||||
|
res.insert(tr("Allocated"), QString::fromLatin1("%1 bytes").arg(ev->allocated));
|
||||||
|
res.insert(tr("Allocations"), QString::number(ev->allocations));
|
||||||
|
}
|
||||||
|
if (ev->deallocations > 0) {
|
||||||
|
res.insert(tr("Deallocated"), QString::fromLatin1("%1 bytes").arg(-ev->deallocated));
|
||||||
|
res.insert(tr("Deallocations"), QString::number(ev->deallocations));
|
||||||
|
}
|
||||||
res.insert(tr("Type"), QVariant(MemoryUsageModelPrivate::memoryTypeName(ev->type)));
|
res.insert(tr("Type"), QVariant(MemoryUsageModelPrivate::memoryTypeName(ev->type)));
|
||||||
if (ev->originTypeIndex != -1) {
|
if (ev->originTypeIndex != -1) {
|
||||||
res.insert(tr("Location"),
|
res.insert(tr("Location"),
|
||||||
@@ -189,9 +196,7 @@ void MemoryUsageModel::loadData()
|
|||||||
int currentJSHeapIndex = -1;
|
int currentJSHeapIndex = -1;
|
||||||
|
|
||||||
QStack<RangeStackFrame> rangeStack;
|
QStack<RangeStackFrame> rangeStack;
|
||||||
MemoryAllocation dummy = {
|
MemoryAllocation dummy;
|
||||||
QmlDebug::MaximumMemoryType, -1, -1 , -1
|
|
||||||
};
|
|
||||||
|
|
||||||
const QVector<QmlProfilerDataModel::QmlEventTypeData> &types = simpleModel->getEventTypes();
|
const QVector<QmlProfilerDataModel::QmlEventTypeData> &types = simpleModel->getEventTypes();
|
||||||
foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) {
|
foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) {
|
||||||
@@ -207,18 +212,18 @@ void MemoryUsageModel::loadData()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type.detailType == QmlDebug::SmallItem || type.detailType == QmlDebug::LargeItem) {
|
if (type.detailType == QmlDebug::SmallItem || type.detailType == QmlDebug::LargeItem) {
|
||||||
currentUsage += event.numericData1;
|
|
||||||
MemoryAllocation &last = currentUsageIndex > -1 ? d->data(currentUsageIndex) : dummy;
|
MemoryAllocation &last = currentUsageIndex > -1 ? d->data(currentUsageIndex) : dummy;
|
||||||
if (!rangeStack.empty() && last.originTypeIndex == rangeStack.top().originTypeIndex) {
|
if (!rangeStack.empty() && type.detailType == last.type &&
|
||||||
last.size = currentUsage;
|
last.originTypeIndex == rangeStack.top().originTypeIndex &&
|
||||||
last.delta += event.numericData1;
|
rangeStack.top().startTime < d->range(currentUsageIndex).start) {
|
||||||
|
last.update(event.numericData1);
|
||||||
|
currentUsage = last.size;
|
||||||
} else {
|
} else {
|
||||||
MemoryAllocation allocation = {
|
MemoryAllocation allocation(QmlDebug::SmallItem, currentUsage,
|
||||||
QmlDebug::SmallItem,
|
rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex);
|
||||||
currentUsage,
|
allocation.update(event.numericData1);
|
||||||
event.numericData1,
|
currentUsage = allocation.size;
|
||||||
rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex
|
|
||||||
};
|
|
||||||
if (currentUsageIndex != -1) {
|
if (currentUsageIndex != -1) {
|
||||||
d->insertEnd(currentUsageIndex,
|
d->insertEnd(currentUsageIndex,
|
||||||
event.startTime - d->range(currentUsageIndex).start - 1);
|
event.startTime - d->range(currentUsageIndex).start - 1);
|
||||||
@@ -228,18 +233,17 @@ void MemoryUsageModel::loadData()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type.detailType == QmlDebug::HeapPage || type.detailType == QmlDebug::LargeItem) {
|
if (type.detailType == QmlDebug::HeapPage || type.detailType == QmlDebug::LargeItem) {
|
||||||
currentSize += event.numericData1;
|
|
||||||
MemoryAllocation &last = currentJSHeapIndex > -1 ? d->data(currentJSHeapIndex) : dummy;
|
MemoryAllocation &last = currentJSHeapIndex > -1 ? d->data(currentJSHeapIndex) : dummy;
|
||||||
if (!rangeStack.empty() && last.originTypeIndex == rangeStack.top().originTypeIndex) {
|
if (!rangeStack.empty() && type.detailType == last.type &&
|
||||||
last.size = currentSize;
|
last.originTypeIndex == rangeStack.top().originTypeIndex &&
|
||||||
last.delta += event.numericData1;
|
rangeStack.top().startTime < d->range(currentJSHeapIndex).start) {
|
||||||
|
last.update(event.numericData1);
|
||||||
|
currentSize = last.size;
|
||||||
} else {
|
} else {
|
||||||
MemoryAllocation allocation = {
|
MemoryAllocation allocation((QmlDebug::MemoryType)type.detailType, currentSize,
|
||||||
(QmlDebug::MemoryType)type.detailType,
|
rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex);
|
||||||
currentSize,
|
allocation.update(event.numericData1);
|
||||||
event.numericData1,
|
currentSize = allocation.size;
|
||||||
rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex
|
|
||||||
};
|
|
||||||
|
|
||||||
if (currentSize > d->maxSize)
|
if (currentSize > d->maxSize)
|
||||||
d->maxSize = currentSize;
|
d->maxSize = currentSize;
|
||||||
@@ -286,6 +290,25 @@ QString MemoryUsageModel::MemoryUsageModelPrivate::memoryTypeName(int type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MemoryUsageModel::MemoryAllocation::MemoryAllocation(QmlDebug::MemoryType type, qint64 baseAmount,
|
||||||
|
int originTypeIndex) :
|
||||||
|
type(type), size(baseAmount), allocated(0), deallocated(0), allocations(0), deallocations(0),
|
||||||
|
originTypeIndex(originTypeIndex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryUsageModel::MemoryAllocation::update(qint64 amount)
|
||||||
|
{
|
||||||
|
size += amount;
|
||||||
|
if (amount < 0) {
|
||||||
|
deallocated += amount;
|
||||||
|
++deallocations;
|
||||||
|
} else {
|
||||||
|
allocated += amount;
|
||||||
|
++allocations;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace QmlProfilerExtension
|
} // namespace QmlProfilerExtension
|
||||||
|
@@ -37,8 +37,15 @@ public:
|
|||||||
struct MemoryAllocation {
|
struct MemoryAllocation {
|
||||||
QmlDebug::MemoryType type;
|
QmlDebug::MemoryType type;
|
||||||
qint64 size;
|
qint64 size;
|
||||||
qint64 delta;
|
qint64 allocated;
|
||||||
|
qint64 deallocated;
|
||||||
|
int allocations;
|
||||||
|
int deallocations;
|
||||||
int originTypeIndex;
|
int originTypeIndex;
|
||||||
|
|
||||||
|
MemoryAllocation(QmlDebug::MemoryType type = QmlDebug::MaximumMemoryType,
|
||||||
|
qint64 baseAmount = 0, int originTypeIndex = -1);
|
||||||
|
void update(qint64 amount);
|
||||||
};
|
};
|
||||||
|
|
||||||
MemoryUsageModel(QObject *parent = 0);
|
MemoryUsageModel(QObject *parent = 0);
|
||||||
|
Reference in New Issue
Block a user