diff options
author | Christiaan Janssen <christiaan.janssen@digia.com> | 2013-06-19 15:12:32 +0200 |
---|---|---|
committer | Kai Koehne <kai.koehne@digia.com> | 2013-06-20 12:19:08 +0300 |
commit | 0ce1d6751c81476220d9e14e29a0c1d814847873 (patch) | |
tree | 9db1928afc05cc08768f7a716c518950a2919944 | |
parent | 698958c92dbed25129c6cb6c4e58de3ab965bba0 (diff) | |
download | qt-creator-0ce1d6751c81476220d9e14e29a0c1d814847873.tar.gz |
QmlProfilerExtended: Pixmap Cache model
Change-Id: Ib0ac48b30406269a6090dbbc6e047653e279a9bf
Reviewed-by: Kai Koehne <kai.koehne@digia.com>
-rw-r--r-- | libs/qmldebug/qmlprofilertraceclient.cpp | 15 | ||||
-rw-r--r-- | libs/qmldebug/qmlprofilertraceclient.h | 12 | ||||
-rw-r--r-- | plugins/qmlprofiler/qmlprofilerclientmanager.cpp | 8 | ||||
-rw-r--r-- | plugins/qmlprofiler/qmlprofilerclientmanager.h | 1 | ||||
-rw-r--r-- | plugins/qmlprofiler/qmlprofilermodelmanager.cpp | 11 | ||||
-rw-r--r-- | plugins/qmlprofiler/qmlprofilermodelmanager.h | 2 | ||||
-rw-r--r-- | plugins/qmlprofiler/qmlprofilersimplemodel.cpp | 7 | ||||
-rw-r--r-- | plugins/qmlprofiler/qmlprofilersimplemodel.h | 1 | ||||
-rw-r--r-- | plugins/qmlprofiler/qmlprofilertool.cpp | 4 | ||||
-rw-r--r-- | plugins/qmlprofilerextended/pixmapcachemodel.cpp | 550 | ||||
-rw-r--r-- | plugins/qmlprofilerextended/pixmapcachemodel.h | 120 | ||||
-rw-r--r-- | plugins/qmlprofilerextended/qmlprofilerextended.pro | 10 | ||||
-rw-r--r-- | plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp | 2 |
13 files changed, 739 insertions, 4 deletions
diff --git a/libs/qmldebug/qmlprofilertraceclient.cpp b/libs/qmldebug/qmlprofilertraceclient.cpp index 22c38b81fb..49a4b2bb8d 100644 --- a/libs/qmldebug/qmlprofilertraceclient.cpp +++ b/libs/qmldebug/qmlprofilertraceclient.cpp @@ -191,6 +191,21 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data) stream >> params[count++]; } emit sceneGraphFrame(SceneGraphFrameEvent, sgEventType, time, params[0], params[1], params[2], params[3], params[4]); + } else if (messageType == PixmapCacheEvent) { + int pixEvTy, width = -1, height = -1, refcount = -1; + QString pixUrl; + stream >> pixEvTy >> pixUrl; + if (pixEvTy == (int)PixmapReferenceCountChanged || pixEvTy == (int)PixmapCacheCountChanged) { + stream >> refcount; + emit pixmapCacheEvent(time,pixEvTy, pixUrl, 0, 0, refcount); + } else + if (pixEvTy == (int)PixmapSizeKnown) { + stream >> width >> height; + emit pixmapCacheEvent(time,pixEvTy, pixUrl, width, height, 1); + } else { // Other + emit pixmapCacheEvent(time,pixEvTy, pixUrl, 0, 0, 0); + } + d->maximumTime = qMax(time, d->maximumTime); } else { int range; stream >> range; diff --git a/libs/qmldebug/qmlprofilertraceclient.h b/libs/qmldebug/qmlprofilertraceclient.h index 83c4e8772c..21c7d4eae1 100644 --- a/libs/qmldebug/qmlprofilertraceclient.h +++ b/libs/qmldebug/qmlprofilertraceclient.h @@ -77,6 +77,17 @@ public: MaximumMessage }; + enum PixmapEventType { + PixmapSizeKnown, + PixmapReferenceCountChanged, + PixmapCacheCountChanged, + PixmapLoadingStarted, + PixmapLoadingFinished, + PixmapLoadingError, + + MaximumPixmapEventType + }; + bool isEnabled() const; bool isRecording() const; void setRecording(bool); @@ -95,6 +106,7 @@ signals: const QStringList &data, const QmlDebug::QmlEventLocation &location); void frame(qint64 time, int frameRate, int animationCount); void sceneGraphFrame(int eventType, int sgEventType, qint64 time, qint64 param1, qint64 param2, qint64 param3, qint64 param4, qint64 param5); + void pixmapCacheEvent(qint64 time, int cacheEventType, const QString& url, int width, int height, int refCount); void recordingChanged(bool arg); diff --git a/plugins/qmlprofiler/qmlprofilerclientmanager.cpp b/plugins/qmlprofiler/qmlprofilerclientmanager.cpp index 72fabc7a58..b29344699e 100644 --- a/plugins/qmlprofiler/qmlprofilerclientmanager.cpp +++ b/plugins/qmlprofiler/qmlprofilerclientmanager.cpp @@ -171,6 +171,10 @@ void QmlProfilerClientManager::connectClientSignals() connect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)), this, SIGNAL(addFrameEvent(qint64,int,int))); connect(d->qmlclientplugin.data(), + SIGNAL(pixmapCacheEvent(qint64,int,QString,int,int,int)), + this, + SIGNAL(addPixmapCacheEvent(qint64,int,QString,int,int,int))); + connect(d->qmlclientplugin.data(), SIGNAL(sceneGraphFrame(int,int,qint64,qint64,qint64,qint64,qint64,qint64)), this, SIGNAL(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64))); @@ -207,6 +211,10 @@ void QmlProfilerClientManager::disconnectClientSignals() disconnect(d->qmlclientplugin.data(), SIGNAL(frame(qint64,int,int)), this, SIGNAL(addFrameEvent(qint64,int,int))); disconnect(d->qmlclientplugin.data(), + SIGNAL(pixmapCacheEvent(qint64,int,QString,int,int,int)), + this, + SIGNAL(addPixmapCacheEvent(qint64,int,QString,int,int,int))); + disconnect(d->qmlclientplugin.data(), SIGNAL(sceneGraphFrame(int,int,qint64,qint64,qint64,qint64,qint64,qint64,qint64)), this, SIGNAL(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64,qint64))); diff --git a/plugins/qmlprofiler/qmlprofilerclientmanager.h b/plugins/qmlprofiler/qmlprofilerclientmanager.h index fdf643ae1c..9401b554f0 100644 --- a/plugins/qmlprofiler/qmlprofilerclientmanager.h +++ b/plugins/qmlprofiler/qmlprofilerclientmanager.h @@ -67,6 +67,7 @@ signals: void traceFinished(qint64); void dataReadyForProcessing(); void addSceneGraphEvent(int, int, qint64, qint64, qint64, qint64, qint64, qint64); + void addPixmapCacheEvent(qint64,int,QString,int,int,int); public slots: void connectClient(quint16 port); diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp index 9f6b8725dc..bd47bea32b 100644 --- a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp +++ b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp @@ -222,6 +222,17 @@ void QmlProfilerModelManager::addSceneGraphEvent(int eventType, int SGEtype, qin emit countChanged(); } +void QmlProfilerModelManager::addPixmapCacheEvent(qint64 time, int pixmapEventType, QString Url, int pixmapWidth, int pixmapHeight, int referenceCount) +{ + if (d->traceTime->startTime() == -1) + d->traceTime->setStartTime(time); + + QTC_ASSERT(state() == QmlProfilerDataState::AcquiringData, /**/); + d->model->addPixmapCacheEvent(time, pixmapEventType, Url, pixmapWidth, pixmapHeight, referenceCount); + emit countChanged(); +} + + void QmlProfilerModelManager::complete() { if (state() == QmlProfilerDataState::AcquiringData) { diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.h b/plugins/qmlprofiler/qmlprofilermodelmanager.h index faa4d53fe8..df033ff122 100644 --- a/plugins/qmlprofiler/qmlprofilermodelmanager.h +++ b/plugins/qmlprofiler/qmlprofilermodelmanager.h @@ -122,6 +122,8 @@ public slots: const QStringList &data, const QmlDebug::QmlEventLocation &location); void addSceneGraphEvent(int eventType, int SGEtype, qint64 startTime, qint64 timing1, qint64 timing2, qint64 timing3, qint64 timing4, qint64 timing5); + void addPixmapCacheEvent(qint64 time, int pixmapEventType, QString Url, + int pixmapWidth, int pixmapHeight, int referenceCount); void addV8Event(int depth, const QString &function,const QString &filename, int lineNumber, double totalTime, double selfTime); diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp index bf2985de45..52ddc3ac99 100644 --- a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp +++ b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp @@ -88,6 +88,13 @@ void QmlProfilerSimpleModel::addSceneGraphEvent(int eventType, int SGEtype, qint eventList.append(eventData); } +void QmlProfilerSimpleModel::addPixmapCacheEvent(qint64 time, int cacheEventType, const QString &url, int width, int height, int refCount) +{ + QmlDebug::QmlEventLocation location(url, 0, 0); + QmlEventData eventData = {QString(), QmlDebug::PixmapCacheEvent, cacheEventType, time, 0, QStringList(), location, width, height, refCount, -1, -1}; + eventList.append(eventData); +} + qint64 QmlProfilerSimpleModel::lastTimeMark() const { if (eventList.isEmpty()) diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.h b/plugins/qmlprofiler/qmlprofilersimplemodel.h index c2c2c01bb0..e556a7a5d3 100644 --- a/plugins/qmlprofiler/qmlprofilersimplemodel.h +++ b/plugins/qmlprofiler/qmlprofilersimplemodel.h @@ -71,6 +71,7 @@ public: void addRangedEvent(int type, int bindingType, qint64 startTime, qint64 length, const QStringList &data, const QmlDebug::QmlEventLocation &location); void addFrameEvent(qint64 time, int framerate, int animationcount); void addSceneGraphEvent(int eventType, int SGEtype, qint64 startTime, qint64 timing1, qint64 timing2, qint64 timing3, qint64 timing4, qint64 timing5); + void addPixmapCacheEvent(qint64 time, int cacheEventType, const QString& url, int width, int height, int refCount); qint64 lastTimeMark() const; virtual void complete(); diff --git a/plugins/qmlprofiler/qmlprofilertool.cpp b/plugins/qmlprofiler/qmlprofilertool.cpp index 52bc43d207..a0e0cfe454 100644 --- a/plugins/qmlprofiler/qmlprofilertool.cpp +++ b/plugins/qmlprofiler/qmlprofilertool.cpp @@ -158,6 +158,10 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent) d->m_profilerModelManager, SLOT(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64))); connect(d->m_profilerConnections, + SIGNAL(addPixmapCacheEvent(qint64,int,QString,int,int,int)), + d->m_profilerModelManager, + SLOT(addPixmapCacheEvent(qint64,int,QString,int,int,int))); + connect(d->m_profilerConnections, SIGNAL(addV8Event(int,QString,QString,int,double,double)), d->m_profilerModelManager, SLOT(addV8Event(int,QString,QString,int,double,double))); diff --git a/plugins/qmlprofilerextended/pixmapcachemodel.cpp b/plugins/qmlprofilerextended/pixmapcachemodel.cpp new file mode 100644 index 0000000000..4fb118eb29 --- /dev/null +++ b/plugins/qmlprofilerextended/pixmapcachemodel.cpp @@ -0,0 +1,550 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +****************************************************************************/ + +#include "pixmapcachemodel.h" +#include "qmldebug/qmlprofilereventtypes.h" +#include "qmlprofiler/qmlprofilermodelmanager.h" + +#include <QDebug> + +namespace QmlProfilerExtended { +namespace Internal { + +using namespace QmlProfiler::Internal; + +class PixmapCacheModel::PixmapCacheModelPrivate { +public: + PixmapCacheModelPrivate(PixmapCacheModel *qq):q(qq) {} + + ~PixmapCacheModelPrivate(); + + PixmapCacheModel *q; + + void computeCacheSizes(); + void resizeUnfinishedLoads(); + void flattenLoads(); + void computeRowCounts(); + + QVector < PixmapCacheModel::PixmapCacheEvent > eventList; + QVector < QString > pixmapUrls; + QVector < QPair<int, int> > pixmapSizes; + bool isExpanded; + int expandedRowCount; + int collapsedRowCount; + QString displayTime(double time); + void addVP(QVariantList &l, QString label, qint64 time); + + qint64 minCacheSize; + qint64 maxCacheSize; +}; + +PixmapCacheModel::PixmapCacheModel(QObject *parent) + : AbstractTimelineModel(parent), d(new PixmapCacheModelPrivate(this)) +{ + d->collapsedRowCount = 1; + d->expandedRowCount = 1; +} + +PixmapCacheModel::~PixmapCacheModel() +{ +} + +int PixmapCacheModel::categories() const +{ + return 1; +} + +QStringList PixmapCacheModel::categoryTitles() const +{ + QStringList retString; + retString << categoryLabel(0); + return retString; +} + +QString PixmapCacheModel::name() const +{ + return QLatin1String("PixmapCacheTimeLineModel"); +} + +int PixmapCacheModel::count() const +{ + return d->eventList.count(); +} + +bool PixmapCacheModel::isEmpty() const +{ + return d->eventList.isEmpty(); +} + +bool PixmapCacheModel::eventAccepted(const QmlProfiler::Internal::QmlProfilerSimpleModel::QmlEventData &event) const +{ + return (event.eventType == QmlDebug::PixmapCacheEvent); +} + +qint64 PixmapCacheModel::lastTimeMark() const +{ + return d->eventList.last().startTime; +} + +void PixmapCacheModel::setExpanded(int category, bool expanded) +{ + d->isExpanded = expanded; +} + +int PixmapCacheModel::categoryDepth(int categoryIndex) const +{ + Q_UNUSED(categoryIndex); + if (isEmpty()) + return 1; + if (d->isExpanded) + return d->expandedRowCount; + return d->collapsedRowCount; +} + +int PixmapCacheModel::categoryCount() const +{ + return 1; +} + +const QString PixmapCacheModel::categoryLabel(int categoryIndex) const +{ + Q_UNUSED(categoryIndex); + return QLatin1String("Pixmap Cache"); +} + +int PixmapCacheModel::findFirstIndex(qint64 startTime) const +{ + // TODO properly + int candidate = -2; + for (int i=0; i < d->eventList.count(); i++) + if (d->eventList[i].startTime + d->eventList[i].duration > startTime) { + candidate = i; + break; + } + + if (candidate == -1) + return 0; + if (candidate == -2) + return d->eventList.count() - 1; + + return candidate; +} + +int PixmapCacheModel::findFirstIndexNoParents(qint64 startTime) const +{ + // TODO properly + return findFirstIndex(startTime); + +// int candidate = -1; +// // in the "endtime" list, find the first event that ends after startTime +// if (d->endTimeData.isEmpty()) +// return 0; // -1 +// if (d->endTimeData.count() == 1 || d->endTimeData.first().endTime >= startTime) +// candidate = 0; +// else +// if (d->endTimeData.last().endTime <= startTime) +// return 0; // -1 + +// if (candidate == -1) { +// int fromIndex = 0; +// int toIndex = d->endTimeData.count()-1; +// while (toIndex - fromIndex > 1) { +// int midIndex = (fromIndex + toIndex)/2; +// if (d->endTimeData[midIndex].endTime < startTime) +// fromIndex = midIndex; +// else +// toIndex = midIndex; +// } + +// candidate = toIndex; +// } + +// int ndx = d->endTimeData[candidate].startTimeIndex; + +// return ndx; +} + +int PixmapCacheModel::findLastIndex(qint64 endTime) const +{ + // TODO properly + int candidate = 0; + for (int i = d->eventList.count()-1; i >= 0; i--) + if (d->eventList[i].startTime < endTime) { + candidate = i; + break; + } + return candidate; +} + +int PixmapCacheModel::getEventType(int index) const +{ + return QmlDebug::PixmapCacheEvent; +} + +int PixmapCacheModel::getEventCategory(int index) const +{ + Q_UNUSED(index); + return 0; +} + +int PixmapCacheModel::getEventRow(int index) const +{ + if (d->isExpanded) + return d->eventList[index].rowNumberExpanded; + return d->eventList[index].rowNumberCollapsed; +} + +qint64 PixmapCacheModel::getDuration(int index) const +{ + return d->eventList[index].duration; +} + +qint64 PixmapCacheModel::getStartTime(int index) const +{ + return d->eventList[index].startTime; +} + +qint64 PixmapCacheModel::getEndTime(int index) const +{ + return getStartTime(index)+getDuration(index); +} + +int PixmapCacheModel::getEventId(int index) const +{ + return d->eventList[index].eventId; +} + +QColor PixmapCacheModel::getColor(int index) const +{ + if (d->eventList[index].pixmapEventType == PixmapCacheCountChanged) + return QColor::fromHsl(240, 76, 166); + + int ndx = getEventId(index); + return QColor::fromHsl((ndx*25)%360, 76, 166); +} + +float PixmapCacheModel::getHeight(int index) const +{ + if (d->eventList[index].pixmapEventType == PixmapCacheCountChanged) { + float scale = d->maxCacheSize - d->minCacheSize; + float fraction = 1.0f; + if (scale > 1) + fraction = (float)(d->eventList[index].cacheSize - + d->minCacheSize) / scale; + + return fraction * 0.85f + 0.15f; + } + + return 1.0f; +} + +QString getFilenameOnly(QString absUrl) +{ + int characterPos = absUrl.lastIndexOf(QLatin1Char('/'))+1; + if (characterPos < absUrl.length()) + absUrl = absUrl.mid(characterPos); + return absUrl; +} + +const QVariantList PixmapCacheModel::getLabelsForCategory(int category) const +{ + QVariantList result; + + if (d->isExpanded && !isEmpty()) { + { + // Cache Size + QVariantMap element; + element.insert(QLatin1String("displayName"), QVariant(QLatin1String("Cache Size"))); + element.insert(QLatin1String("description"), QVariant(QLatin1String("Cache Size"))); + + element.insert(QLatin1String("id"), QVariant(0)); + result << element; + } + + for (int i=0; i < d->pixmapUrls.count(); i++) { + // Loading + QVariantMap element; + element.insert(QLatin1String("displayName"), QVariant(getFilenameOnly(d->pixmapUrls[i]))); + element.insert(QLatin1String("description"), QVariant(getFilenameOnly(d->pixmapUrls[i]))); + + element.insert(QLatin1String("id"), QVariant(i+1)); + result << element; + } + } + + return result; +} + +QString PixmapCacheModel::PixmapCacheModelPrivate::displayTime(double time) +{ + if (time < 1e6) + return QString::number(time/1e3,'f',3) + trUtf8(" \xc2\xb5s"); + if (time < 1e9) + return QString::number(time/1e6,'f',3) + tr(" ms"); + + return QString::number(time/1e9,'f',3) + tr(" s"); +} + +void PixmapCacheModel::PixmapCacheModelPrivate::addVP(QVariantList &l, QString label, qint64 time) +{ + if (time > 0) { + QVariantMap res; + res.insert(label, QVariant(displayTime(time))); + l << res; + } +} + +const QVariantList PixmapCacheModel::getEventDetails(int index) const +{ + QVariantList result; + PixmapCacheEvent *ev = &d->eventList[index]; + + { + QVariantMap res; + if (ev->pixmapEventType == PixmapCacheCountChanged) + res.insert(QLatin1String("title"), QVariant(QLatin1String("Image Cached"))); + else if (ev->pixmapEventType == PixmapLoadingStarted) + res.insert(QLatin1String("title"), QVariant(QLatin1String("Image Loaded"))); + result << res; + } + + if (ev->pixmapEventType != PixmapCacheCountChanged) { + d->addVP(result, tr("Duration"), ev->duration ); + } + + { + QVariantMap res; + res.insert(tr("File"), QVariant(getFilenameOnly(d->pixmapUrls[ev->urlIndex]))); + result << res; + } + + { + QVariantMap res; + res.insert(tr("Width"), QVariant(QString::fromLatin1("%1 px").arg(d->pixmapSizes[ev->urlIndex].first))); + result << res; + res.clear(); + res.insert(tr("Height"), QVariant(QString::fromLatin1("%1 px").arg(d->pixmapSizes[ev->urlIndex].second))); + result << res; + } + + if (ev->pixmapEventType == PixmapLoadingStarted && ev->cacheSize == -1) { + QVariantMap res; + res.insert(tr("Result"), QVariant(QLatin1String("Load Error"))); + result << res; + } + + return result; +} + +const QVariantMap PixmapCacheModel::getEventLocation(int /*index*/) const +{ + QVariantMap map; + return map; +} + +bool compareStartTimes(const PixmapCacheModel::PixmapCacheEvent&t1, const PixmapCacheModel::PixmapCacheEvent &t2) +{ + return t1.startTime < t2.startTime; +} + +void PixmapCacheModel::loadData() +{ + clear(); + QmlProfilerSimpleModel *simpleModel = m_modelManager->simpleModel(); + if (simpleModel->isEmpty()) + return; + + int lastCacheSizeEvent = -1; + int cumulatedCount = 0; + QVector < int > pixmapStartPoints; + + foreach (const QmlProfilerSimpleModel::QmlEventData &event, simpleModel->getEvents()) { + if (!eventAccepted(event)) + continue; + + PixmapCacheEvent newEvent; + newEvent.pixmapEventType = event.bindingType; + newEvent.startTime = event.startTime; + newEvent.duration = 0; + + bool isNewEntry = false; + newEvent.urlIndex = d->pixmapUrls.indexOf(event.location.filename); + if (newEvent.urlIndex == -1) { + isNewEntry = true; + newEvent.urlIndex = d->pixmapUrls.count(); + d->pixmapUrls << event.location.filename; + d->pixmapSizes << QPair<int, int>(0,0); // default value + pixmapStartPoints << d->eventList.count(); // index to the starting point + } + + if (newEvent.pixmapEventType == PixmapSizeKnown) { // pixmap size + d->pixmapSizes[newEvent.urlIndex] = QPair<int,int>((int)event.numericData1, (int)event.numericData2); + } + + newEvent.eventId = newEvent.urlIndex + 1; + + // Cache Size Changed Event + if (newEvent.pixmapEventType == PixmapCacheCountChanged) { + newEvent.startTime = event.startTime + 1; // delay 1 ns for proper sorting + newEvent.eventId = 0; + newEvent.rowNumberExpanded = 1; + newEvent.rowNumberCollapsed = 1; + + qint64 pixSize = d->pixmapSizes[newEvent.urlIndex].first * d->pixmapSizes[newEvent.urlIndex].second; + qint64 prevSize = 0; + if (lastCacheSizeEvent != -1) { + prevSize = d->eventList[lastCacheSizeEvent].cacheSize; + if (event.numericData3 < cumulatedCount) + pixSize = -pixSize; + cumulatedCount = event.numericData3; + + d->eventList[lastCacheSizeEvent].duration = newEvent.startTime - d->eventList[lastCacheSizeEvent].startTime; + } + newEvent.cacheSize = prevSize + pixSize; + d->eventList << newEvent; + lastCacheSizeEvent = d->eventList.count() - 1; + } + + // Load + if (newEvent.pixmapEventType == PixmapLoadingStarted) { + pixmapStartPoints[newEvent.urlIndex] = d->eventList.count(); + newEvent.rowNumberExpanded = newEvent.urlIndex + 2; + d->eventList << newEvent; + } + + if (newEvent.pixmapEventType == PixmapLoadingFinished || newEvent.pixmapEventType == PixmapLoadingError) { + int loadIndex = pixmapStartPoints[newEvent.urlIndex]; + if (!isNewEntry) { + d->eventList[loadIndex].duration = event.startTime - d->eventList[loadIndex].startTime; + } else { + // if it's a new entry it means that we don't have a corresponding start + newEvent.pixmapEventType = PixmapLoadingStarted; + newEvent.rowNumberExpanded = newEvent.urlIndex + 2; + newEvent.startTime = traceStartTime(); + newEvent.duration = event.startTime - traceStartTime(); + d->eventList << newEvent; + } + if (event.bindingType == PixmapLoadingFinished) + d->eventList[loadIndex].cacheSize = 1; // use count to mark success + else + d->eventList[loadIndex].cacheSize = -1; // ... or failure + } + } + + if (lastCacheSizeEvent != -1) { + d->eventList[lastCacheSizeEvent].duration = traceEndTime() - d->eventList[lastCacheSizeEvent].startTime; + } + + d->resizeUnfinishedLoads(); + + qSort(d->eventList.begin(), d->eventList.end(), compareStartTimes); + + d->computeCacheSizes(); + d->flattenLoads(); + d->computeRowCounts(); +} + +void PixmapCacheModel::clear() +{ + d->eventList.clear(); + d->pixmapUrls.clear(); + d->pixmapSizes.clear(); + d->collapsedRowCount = 1; + d->expandedRowCount = 1; +} + +void PixmapCacheModel::dataChanged() +{ + if (m_modelManager->state() == QmlProfilerDataState::Done) + loadData(); + + if (m_modelManager->state() == QmlProfilerDataState::Empty) + clear(); + + emit stateChanged(); + emit dataAvailable(); + emit emptyChanged(); + return; +} + +void PixmapCacheModel::PixmapCacheModelPrivate::computeCacheSizes() +{ + minCacheSize = -1; + maxCacheSize = -1; + foreach (const PixmapCacheModel::PixmapCacheEvent &event, eventList) { + if (event.pixmapEventType == PixmapCacheModel::PixmapCacheCountChanged) { + if (minCacheSize == -1 || event.cacheSize < minCacheSize) + minCacheSize = event.cacheSize; + if (maxCacheSize == -1 || event.cacheSize > maxCacheSize) + maxCacheSize = event.cacheSize; + } + } +} + +void PixmapCacheModel::PixmapCacheModelPrivate::resizeUnfinishedLoads() +{ + // all the "load start" events with duration 0 continue till the end of the trace + for (int i = 0; i < eventList.count(); i++) { + if (eventList[i].pixmapEventType == PixmapCacheModel::PixmapLoadingStarted && + eventList[i].duration == 0) { + eventList[i].duration = q->traceEndTime() - eventList[i].startTime; + } + } +} + +void PixmapCacheModel::PixmapCacheModelPrivate::flattenLoads() +{ + // computes "compressed row" + QVector <qint64> eventEndTimes; + for (int i = 0; i < eventList.count(); i++) { + PixmapCacheModel::PixmapCacheEvent *event = &eventList[i]; + if (event->pixmapEventType == PixmapCacheModel::PixmapLoadingStarted) { + event->rowNumberCollapsed = 0; + while (eventEndTimes.count() > event->rowNumberCollapsed && + eventEndTimes[event->rowNumberCollapsed] > event->startTime) + event->rowNumberCollapsed++; + + if (eventEndTimes.count() == event->rowNumberCollapsed) + eventEndTimes << 0; // increase stack length, proper value added below + eventEndTimes[event->rowNumberCollapsed] = event->startTime + event->duration; + + // readjust to account for category empty row and bargraph + event->rowNumberCollapsed += 2; + } + } +} + +void PixmapCacheModel::PixmapCacheModelPrivate::computeRowCounts() +{ + expandedRowCount = 0; + collapsedRowCount = 0; + foreach (const PixmapCacheModel::PixmapCacheEvent &event, eventList) { + if (event.rowNumberExpanded > expandedRowCount) + expandedRowCount = event.rowNumberExpanded; + if (event.rowNumberCollapsed > collapsedRowCount) + collapsedRowCount = event.rowNumberCollapsed; + } + + // Starting from 0, count is maxIndex+1 + expandedRowCount++; + collapsedRowCount++; +} + + + +} // namespace Internal +} // namespace QmlProfilerExtended diff --git a/plugins/qmlprofilerextended/pixmapcachemodel.h b/plugins/qmlprofilerextended/pixmapcachemodel.h new file mode 100644 index 0000000000..d2bbfee06a --- /dev/null +++ b/plugins/qmlprofilerextended/pixmapcachemodel.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +****************************************************************************/ + +#ifndef PIXMAPCACHEMODEL_H +#define PIXMAPCACHEMODEL_H + +#include "qmlprofiler/abstracttimelinemodel.h" +#include "qmlprofiler/qmlprofilermodelmanager.h" +#include "qmlprofiler/qmlprofilersimplemodel.h" + +#include <QStringList> +#include <QColor> + +namespace QmlProfilerExtended { +namespace Internal { + +class PixmapCacheModel : public QmlProfiler::AbstractTimelineModel +{ + Q_OBJECT +public: + + struct PixmapCacheEvent { + int eventId; + qint64 startTime; + qint64 duration; + int pixmapEventType; + int urlIndex; + qint64 cacheSize; + int rowNumberExpanded; + int rowNumberCollapsed; + }; + + enum PixmapEventType { + PixmapSizeKnown, + PixmapReferenceCountChanged, + PixmapCacheCountChanged, + PixmapLoadingStarted, + PixmapLoadingFinished, + PixmapLoadingError, + + MaximumPixmapEventType + }; + + PixmapCacheModel(QObject *parent = 0); + ~PixmapCacheModel(); + + +// void setModelManager(QmlProfiler::Internal::QmlProfilerModelManager *modelManager); + + int categories() const; + QStringList categoryTitles() const; + QString name() const; + int count() const; + + bool isEmpty() const; + + bool eventAccepted(const QmlProfiler::Internal::QmlProfilerSimpleModel::QmlEventData &event) const; + + Q_INVOKABLE qint64 lastTimeMark() const; + + Q_INVOKABLE void setExpanded(int category, bool expanded); + Q_INVOKABLE int categoryDepth(int categoryIndex) const; + Q_INVOKABLE int categoryCount() const; + Q_INVOKABLE const QString categoryLabel(int categoryIndex) const; + + int findFirstIndex(qint64 startTime) const; + int findFirstIndexNoParents(qint64 startTime) const; + int findLastIndex(qint64 endTime) const; + + int getEventType(int index) const; + int getEventCategory(int index) const; + int getEventRow(int index) const; + Q_INVOKABLE qint64 getDuration(int index) const; + Q_INVOKABLE qint64 getStartTime(int index) const; + Q_INVOKABLE qint64 getEndTime(int index) const; + Q_INVOKABLE int getEventId(int index) const; + Q_INVOKABLE QColor getColor(int index) const; + Q_INVOKABLE float getHeight(int index) const; + + Q_INVOKABLE const QVariantList getLabelsForCategory(int category) const; + + Q_INVOKABLE const QVariantList getEventDetails(int index) const; + Q_INVOKABLE const QVariantMap getEventLocation(int index) const; + + void loadData(); + void clear(); +//signals: +// void countChanged(); +// void dataAvailable(); +// void stateChanged(); +// void emptyChanged(); +// void expandedChanged(); + +protected slots: + void dataChanged(); + +private: + class PixmapCacheModelPrivate; + PixmapCacheModelPrivate *d; + +}; + +} // namespace Internal +} // namespace QmlProfilerExtended + +#endif // PIXMAPCACHEMODEL_H diff --git a/plugins/qmlprofilerextended/qmlprofilerextended.pro b/plugins/qmlprofilerextended/qmlprofilerextended.pro index 213f149817..e35215883d 100644 --- a/plugins/qmlprofilerextended/qmlprofilerextended.pro +++ b/plugins/qmlprofilerextended/qmlprofilerextended.pro @@ -9,12 +9,14 @@ DEFINES += QMLPROFILEREXTENDED_LIBRARY # QmlProfilerExtended files SOURCES += qmlprofilerextendedplugin.cpp \ - scenegraphtimelinemodel.cpp + scenegraphtimelinemodel.cpp \ + pixmapcachemodel.cpp -HEADERS += qmlprofilerextendedplugin.h\ - qmlprofilerextended_global.h\ +HEADERS += qmlprofilerextendedplugin.h \ + qmlprofilerextended_global.h \ qmlprofilerextendedconstants.h \ - scenegraphtimelinemodel.h + scenegraphtimelinemodel.h \ + pixmapcachemodel.h OTHER_FILES += \ QmlProfilerExtended.json diff --git a/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp b/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp index 5c6fcb8e70..1eeb64a173 100644 --- a/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp +++ b/plugins/qmlprofilerextended/qmlprofilerextendedplugin.cpp @@ -33,6 +33,7 @@ #include <QtPlugin> #include "scenegraphtimelinemodel.h" +#include "pixmapcachemodel.h" using namespace QmlProfilerExtended::Internal; @@ -59,6 +60,7 @@ bool QmlProfilerExtendedPlugin::initialize(const QStringList &arguments, QString Q_UNUSED(arguments) Q_UNUSED(errorString) + addAutoReleasedObject(new PixmapCacheModel); addAutoReleasedObject(new SceneGraphTimelineModel); return true; |