QmlProfiler: Always dispatch memory and pixmap events

These events carry state which needs to be tracked even if they are
outside the current range.

Change-Id: Ia4bc34010f81cec29cd934ce2fefa0c337aef11f
Task-number: QTCREATORBUG-16552
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
Ulf Hermann
2016-07-05 13:04:40 +02:00
parent 42d3f501a1
commit d2c9466d79
3 changed files with 75 additions and 27 deletions

View File

@@ -177,11 +177,19 @@ void MemoryUsageModel::loadEvent(const QmlEvent &event, const QmlEventType &type
m_currentUsage = allocation.size;
if (m_currentUsageIndex != -1) {
insertEnd(m_currentUsageIndex,
event.timestamp() - startTime(m_currentUsageIndex) - 1);
}
qint64 duration = event.timestamp() - startTime(m_currentUsageIndex);
if (duration > 0) {
insertEnd(m_currentUsageIndex, duration - 1);
m_currentUsageIndex = insertStart(event.timestamp(), SmallItem);
m_data.insert(m_currentUsageIndex, allocation);
} else {
// Ignore ranges of 0 duration. We only need to keep track of the sizes.
m_data[m_currentUsageIndex] = allocation;
}
} else {
m_currentUsageIndex = insertStart(event.timestamp(), SmallItem);
m_data.insert(m_currentUsageIndex, allocation);
}
m_continuation = m_continuation | ContinueUsage;
}
}
@@ -201,11 +209,22 @@ void MemoryUsageModel::loadEvent(const QmlEvent &event, const QmlEventType &type
if (m_currentSize > m_maxSize)
m_maxSize = m_currentSize;
if (m_currentJSHeapIndex != -1)
insertEnd(m_currentJSHeapIndex,
event.timestamp() - startTime(m_currentJSHeapIndex) - 1);
if (m_currentJSHeapIndex != -1) {
qint64 duration = event.timestamp() - startTime(m_currentJSHeapIndex);
if (duration > 0){
insertEnd(m_currentJSHeapIndex, duration - 1);
m_currentJSHeapIndex = insertStart(event.timestamp(), type.detailType());
m_data.insert(m_currentJSHeapIndex, allocation);
} else {
// Ignore ranges of 0 duration. We only need to keep track of the sizes.
m_data[m_currentJSHeapIndex] = allocation;
}
} else {
m_currentJSHeapIndex = insertStart(event.timestamp(), type.detailType());
m_data.insert(m_currentJSHeapIndex, allocation);
}
m_continuation = m_continuation | ContinueAllocation;
}
}
@@ -215,10 +234,10 @@ void MemoryUsageModel::finalize()
{
if (m_currentJSHeapIndex != -1)
insertEnd(m_currentJSHeapIndex, modelManager()->traceTime()->endTime() -
startTime(m_currentJSHeapIndex) - 1);
startTime(m_currentJSHeapIndex));
if (m_currentUsageIndex != -1)
insertEnd(m_currentUsageIndex, modelManager()->traceTime()->endTime() -
startTime(m_currentUsageIndex) - 1);
startTime(m_currentUsageIndex));
computeNesting();

View File

@@ -214,8 +214,6 @@ void PixmapCacheModel::loadEvent(const QmlEvent &event, const QmlEventType &type
break;
}
case PixmapCacheCountChanged: {// Cache Size Changed Event
pixmapStartTime = event.timestamp() + 1; // delay 1 ns for proper sorting
bool uncache = m_cumulatedCount > event.number<qint32>(2);
m_cumulatedCount = event.number<qint32>(2);
qint64 pixSize = 0;
@@ -433,11 +431,16 @@ void PixmapCacheModel::computeMaxCacheSize()
void PixmapCacheModel::resizeUnfinishedLoads()
{
// all the "load start" events with duration 0 continue till the end of the trace
for (int i = 0; i < count(); i++) {
if (m_data[i].pixmapEventType == PixmapCacheModel::PixmapLoadingStarted &&
duration(i) == 0) {
insertEnd(i, modelManager()->traceTime()->endTime() - startTime(i));
// all the unfinished "load start" events continue till the end of the trace
for (auto pixmap = m_pixmaps.begin(), pixmapsEnd = m_pixmaps.end();
pixmap != pixmapsEnd; ++pixmap) {
for (auto size = pixmap->sizes.begin(), sizesEnd = pixmap->sizes.end(); size != sizesEnd;
++size) {
if (size->loadState == Loading) {
insertEnd(size->started,
modelManager()->traceTime()->endTime() - startTime(size->started));
size->loadState = Error;
}
}
}
}
@@ -477,17 +480,26 @@ int PixmapCacheModel::updateCacheCount(int lastCacheSizeEvent,
{
newEvent.pixmapEventType = PixmapCacheCountChanged;
newEvent.rowNumberCollapsed = 1;
newEvent.typeId = typeId;
qint64 prevSize = 0;
int index = lastCacheSizeEvent;
if (lastCacheSizeEvent != -1) {
prevSize = m_data[lastCacheSizeEvent].cacheSize;
insertEnd(lastCacheSizeEvent, pixmapStartTime - startTime(lastCacheSizeEvent));
newEvent.cacheSize = m_data[lastCacheSizeEvent].cacheSize + pixSize;
qint64 duration = pixmapStartTime - startTime(lastCacheSizeEvent);
if (duration > 0) {
insertEnd(lastCacheSizeEvent, duration);
index = insertStart(pixmapStartTime, 0);
m_data.insert(index, newEvent);
} else {
// If the timestamps are the same, just replace it
m_data[index] = newEvent;
}
} else {
newEvent.cacheSize = pixSize;
index = insertStart(pixmapStartTime, 0);
m_data.insert(index, newEvent);
}
newEvent.cacheSize = prevSize + pixSize;
newEvent.typeId = typeId;
int index = insertStart(pixmapStartTime, 0);
m_data.insert(index, newEvent);
return index;
}

View File

@@ -187,6 +187,15 @@ void QmlProfilerDataModel::QmlProfilerDataModelPrivate::rewriteType(int typeInde
detailsRewriter->requestDetailsForLocation(typeIndex, type.location());
}
static bool isStateful(const QmlEventType &type)
{
// Events of these types carry state that has to be taken into account when adding later events:
// PixmapCacheEvent: Total size of the cache and size of pixmap currently being loaded
// MemoryAllocation: Total size of the JS heap and the amount of it currently in use
const Message message = type.message();
return message == PixmapCacheEvent || message == MemoryAllocation;
}
void QmlProfilerDataModel::replayEvents(qint64 rangeStart, qint64 rangeEnd,
QmlProfilerModelManager::EventLoader loader) const
{
@@ -209,8 +218,12 @@ void QmlProfilerDataModel::replayEvents(qint64 rangeStart, qint64 rangeEnd,
stack.push(event);
else if (event.rangeStage() == RangeEnd)
stack.pop();
}
continue;
} else if (isStateful(type)) {
event.setTimestamp(rangeStart);
} else {
continue;
}
} else if (event.timestamp() > rangeEnd) {
if (type.rangeType() != MaximumRangeType) {
if (event.rangeStage() == RangeEnd) {
@@ -224,8 +237,12 @@ void QmlProfilerDataModel::replayEvents(qint64 rangeStart, qint64 rangeEnd,
} else if (event.rangeStage() == RangeStart) {
stack.push(event);
}
}
continue;
} else if (isStateful(type)) {
event.setTimestamp(rangeEnd);
} else {
continue;
}
} else if (!stack.isEmpty()) {
foreach (QmlEvent stashed, stack) {
stashed.setTimestamp(rangeStart);