From 483e607f273e3f70f274e246faeb63af81eefb33 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Tue, 9 Jul 2013 12:28:06 +0200 Subject: QmlProfiler: load and save extra data Change-Id: I97a9bc3c86b330015d1c40850eabbcfa37088521 Reviewed-by: Kai Koehne --- libs/qmldebug/qmlprofilertraceclient.cpp | 2 + plugins/qmlprofiler/qmlprofilermodelmanager.cpp | 6 +- .../qmlprofilerpainteventsmodelproxy.cpp | 9 +- plugins/qmlprofiler/qmlprofilersimplemodel.cpp | 7 +- plugins/qmlprofiler/qmlprofilertracefile.cpp | 105 +++++++++++++++++++-- plugins/qmlprofiler/qmlprofilertracefile.h | 11 ++- 6 files changed, 124 insertions(+), 16 deletions(-) diff --git a/libs/qmldebug/qmlprofilertraceclient.cpp b/libs/qmldebug/qmlprofilertraceclient.cpp index 49a4b2bb8d7..bd0337ca4a7 100644 --- a/libs/qmldebug/qmlprofilertraceclient.cpp +++ b/libs/qmldebug/qmlprofilertraceclient.cpp @@ -190,6 +190,8 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data) while (!stream.atEnd()) { stream >> params[count++]; } + while (count<5) + params[count++] = 0; 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; diff --git a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp index a2a24cc5c08..a06f59b1ab6 100644 --- a/plugins/qmlprofiler/qmlprofilermodelmanager.cpp +++ b/plugins/qmlprofiler/qmlprofilermodelmanager.cpp @@ -302,7 +302,11 @@ void QmlProfilerModelManager::load() SLOT(addRangedEvent(int,int,qint64,qint64,QStringList,QmlDebug::QmlEventLocation))); connect(&reader, SIGNAL(traceStartTime(qint64)), traceTime(), SLOT(setStartTime(qint64))); connect(&reader, SIGNAL(traceEndTime(qint64)), traceTime(), SLOT(setEndTime(qint64))); - + connect(&reader, SIGNAL(sceneGraphFrame(int,int,qint64,qint64,qint64,qint64,qint64,qint64)), + this, SLOT(addSceneGraphEvent(int,int,qint64,qint64,qint64,qint64,qint64,qint64))); + connect(&reader, SIGNAL(pixmapCacheEvent(qint64,int,QString,int,int,int)), + this, SLOT(addPixmapCacheEvent(qint64,int,QString,int,int,int))); + connect(&reader, SIGNAL(frame(qint64,int,int)), this, SLOT(addFrameEvent(qint64,int,int))); reader.setV8DataModel(d->v8Model); reader.load(&file); diff --git a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp index bcb71a96648..6708e7b2263 100644 --- a/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp +++ b/plugins/qmlprofiler/qmlprofilerpainteventsmodelproxy.cpp @@ -151,19 +151,22 @@ void PaintEventsModelProxy::loadData() if (!eventAccepted(event)) continue; + // the profiler registers the animation events at the end of them + qint64 realStartTime = event.startTime - event.duration; + // the duration of the events is estimated from the framerate // we need to correct it before appending a new event if (d->eventList.count() > 0) { QmlPaintEventData *lastEvent = &d->eventList[d->eventList.count()-1]; - if (lastEvent->startTime + lastEvent->duration >= event.startTime) { + if (lastEvent->startTime + lastEvent->duration >= realStartTime) { // 1 nanosecond less to prevent overlap - lastEvent->duration = event.startTime - lastEvent->startTime - 1; + lastEvent->duration = realStartTime - lastEvent->startTime - 1; lastEvent->framerate = 1e9/lastEvent->duration; } } QmlPaintEventData newEvent = { - event.startTime, + realStartTime, event.duration, (int)event.numericData1, (int)event.numericData2 diff --git a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp index ef95ffb881c..1777094c091 100644 --- a/plugins/qmlprofiler/qmlprofilersimplemodel.cpp +++ b/plugins/qmlprofiler/qmlprofilersimplemodel.cpp @@ -78,7 +78,7 @@ void QmlProfilerSimpleModel::addRangedEvent(int type, int bindingType, qint64 st void QmlProfilerSimpleModel::addFrameEvent(qint64 time, int framerate, int animationcount) { qint64 duration = 1e9 / framerate; - QmlEventData eventData = {tr("Animations"), QmlDebug::Painting, QmlDebug::AnimationFrame, time - duration, duration, QStringList(), QmlDebug::QmlEventLocation(), framerate, animationcount, 0, 0, 0}; + QmlEventData eventData = {tr("Animations"), QmlDebug::Painting, QmlDebug::AnimationFrame, time, duration, QStringList(), QmlDebug::QmlEventLocation(), framerate, animationcount, 0, 0, 0}; eventList.append(eventData); } @@ -110,11 +110,12 @@ void QmlProfilerSimpleModel::complete() QString QmlProfilerSimpleModel::getHashString(const QmlProfilerSimpleModel::QmlEventData &event) { - return QString::fromLatin1("%1:%2:%3:%4").arg( + return QString::fromLatin1("%1:%2:%3:%4:%5").arg( event.location.filename, QString::number(event.location.line), QString::number(event.location.column), - QString::number(event.eventType)); + QString::number(event.eventType), + QString::number(event.bindingType)); } diff --git a/plugins/qmlprofiler/qmlprofilertracefile.cpp b/plugins/qmlprofiler/qmlprofilertracefile.cpp index 4ad00ce02c5..52bc3816d36 100644 --- a/plugins/qmlprofiler/qmlprofilertracefile.cpp +++ b/plugins/qmlprofiler/qmlprofilertracefile.cpp @@ -48,6 +48,8 @@ const char TYPE_COMPILING_STR[] = "Compiling"; const char TYPE_CREATING_STR[] = "Creating"; const char TYPE_BINDING_STR[] = "Binding"; const char TYPE_HANDLINGSIGNAL_STR[] = "HandlingSignal"; +const char TYPE_PIXMAPCACHE_STR[] = "PixmapCache"; +const char TYPE_SCENEGRAPH_STR[] = "SceneGraph"; #define _(X) QLatin1String(X) @@ -71,6 +73,10 @@ static QmlEventType qmlEventTypeAsEnum(const QString &typeString) return Binding; } else if (typeString == _(TYPE_HANDLINGSIGNAL_STR)) { return HandlingSignal; + } else if (typeString == _(TYPE_PIXMAPCACHE_STR)) { + return PixmapCacheEvent; + } else if (typeString == _(TYPE_SCENEGRAPH_STR)) { + return SceneGraphFrameEvent; } else { bool isNumber = false; int type = typeString.toUInt(&isNumber); @@ -99,6 +105,12 @@ static QString qmlEventTypeAsString(QmlEventType typeEnum) case HandlingSignal: return _(TYPE_HANDLINGSIGNAL_STR); break; + case PixmapCacheEvent: + return _(TYPE_PIXMAPCACHE_STR); + break; + case SceneGraphFrameEvent: + return _(TYPE_SCENEGRAPH_STR); + break; default: return QString::number((int)typeEnum); } @@ -249,7 +261,10 @@ void QmlProfilerFileReader::loadEventData(QXmlStreamReader &stream) break; } - if (elementName == _("bindingType")) { + if (elementName == _("bindingType") || + elementName == _("animationFrame") || + elementName == _("cacheEventType") || + elementName == _("sgEventType")) { event.bindingType = readData.toInt(); break; } @@ -288,20 +303,45 @@ void QmlProfilerFileReader::loadProfilerDataModel(QXmlStreamReader &stream) switch (token) { case QXmlStreamReader::StartElement: { if (elementName == _("range")) { - Range range = { 0, 0 }; + Range range = { 0, 0, 0, 0, 0, 0, 0 }; const QXmlStreamAttributes attributes = stream.attributes(); if (!attributes.hasAttribute(_("startTime")) - || !attributes.hasAttribute(_("duration")) || !attributes.hasAttribute(_("eventIndex"))) { // ignore incomplete entry continue; } range.startTime = attributes.value(_("startTime")).toString().toLongLong(); - range.duration = attributes.value(_("duration")).toString().toLongLong(); + if (attributes.hasAttribute(_("duration"))) + range.duration = attributes.value(_("duration")).toString().toLongLong(); + + // attributes for special events + if (attributes.hasAttribute(_("framerate"))) + range.numericData1 = attributes.value(_("framerate")).toString().toLongLong(); + if (attributes.hasAttribute(_("animationcount"))) + range.numericData2 = attributes.value(_("animationcount")).toString().toLongLong(); + if (attributes.hasAttribute(_("width"))) + range.numericData1 = attributes.value(_("width")).toString().toLongLong(); + if (attributes.hasAttribute(_("height"))) + range.numericData2 = attributes.value(_("height")).toString().toLongLong(); + if (attributes.hasAttribute(_("refCount"))) + range.numericData3 = attributes.value(_("refCount")).toString().toLongLong(); + if (attributes.hasAttribute(_("timing1"))) + range.numericData1 = attributes.value(_("timing1")).toString().toLongLong(); + if (attributes.hasAttribute(_("timing2"))) + range.numericData2 = attributes.value(_("timing2")).toString().toLongLong(); + if (attributes.hasAttribute(_("timing3"))) + range.numericData3 = attributes.value(_("timing3")).toString().toLongLong(); + if (attributes.hasAttribute(_("timing4"))) + range.numericData4 = attributes.value(_("timing4")).toString().toLongLong(); + if (attributes.hasAttribute(_("timing5"))) + range.numericData5 = attributes.value(_("timing5")).toString().toLongLong(); + + int eventIndex = attributes.value(_("eventIndex")).toString().toInt(); + m_ranges.append(QPair(range, eventIndex)); } break; @@ -332,10 +372,18 @@ void QmlProfilerFileReader::processQmlEvents() QmlEvent &event = m_qmlEvents[eventIndex]; - emit rangedEvent(event.type, event.bindingType, range.startTime, range.duration, + if (event.type == Painting && event.bindingType == QmlDebug::AnimationFrame) { + emit frame(range.startTime, range.numericData1, range.numericData2); + } else if (event.type == PixmapCacheEvent) { + emit pixmapCacheEvent(range.startTime, event.bindingType, event.filename, range.numericData1, range.numericData2, range.numericData3); + } else if (event.type == SceneGraphFrameEvent) { + emit sceneGraphFrame(SceneGraphFrameEvent, event.bindingType, range.startTime, range.numericData1, range.numericData2, range.numericData3, range.numericData4, range.numericData5); + } else { + emit rangedEvent(event.type, event.bindingType, range.startTime, range.duration, QStringList(event.displayName), QmlEventLocation(event.filename, event.line, event.column)); + } } } @@ -377,7 +425,7 @@ void QmlProfilerFileWriter::setQmlEvents(const QVector(r, hashStr)); } @@ -415,7 +463,13 @@ void QmlProfilerFileWriter::save(QIODevice *device) } stream.writeTextElement(_("details"), event.details); if (event.type == Binding) - stream.writeTextElement(_("bindingType"), QString::number((int)event.bindingType)); + stream.writeTextElement(_("bindingType"), QString::number(event.bindingType)); + if (event.type == Painting && event.bindingType == AnimationFrame) + stream.writeTextElement(_("animationFrame"), QString::number(event.bindingType)); + if (event.type == PixmapCacheEvent) + stream.writeTextElement(_("cacheEventType"), QString::number(event.bindingType)); + if (event.type == SceneGraphFrameEvent) + stream.writeTextElement(_("sgEventType"), QString::number(event.bindingType)); stream.writeEndElement(); } stream.writeEndElement(); // eventData @@ -429,10 +483,45 @@ void QmlProfilerFileWriter::save(QIODevice *device) stream.writeStartElement(_("range")); stream.writeAttribute(_("startTime"), QString::number(range.startTime)); - stream.writeAttribute(_("duration"), QString::number(range.duration)); + if (range.duration > 0) // no need to store duration of instantaneous events + stream.writeAttribute(_("duration"), QString::number(range.duration)); stream.writeAttribute(_("eventIndex"), QString::number(m_qmlEvents.keys().indexOf(eventHash))); QmlEvent event = m_qmlEvents.value(eventHash); + + // special: animation event + if (event.type == QmlDebug::Painting && event.bindingType == QmlDebug::AnimationFrame) { + + stream.writeAttribute(_("framerate"), QString::number(range.numericData1)); + stream.writeAttribute(_("animationcount"), QString::number(range.numericData2)); + } + + // special: pixmap cache event + if (event.type == QmlDebug::PixmapCacheEvent) { + // pixmap image size + if (event.bindingType == 0) { + stream.writeAttribute(_("width"), QString::number(range.numericData1)); + stream.writeAttribute(_("height"), QString::number(range.numericData2)); + } + + // reference count (1) / cache size changed (2) + if (event.bindingType == 1 || event.bindingType == 2) + stream.writeAttribute(_("refCount"), QString::number(range.numericData3)); + } + + if (event.type == QmlDebug::SceneGraphFrameEvent) { + // special: scenegraph frame events + if (range.numericData1 > 0) + stream.writeAttribute(_("timing1"), QString::number(range.numericData1)); + if (range.numericData2 > 0) + stream.writeAttribute(_("timing2"), QString::number(range.numericData2)); + if (range.numericData3 > 0) + stream.writeAttribute(_("timing3"), QString::number(range.numericData3)); + if (range.numericData4 > 0) + stream.writeAttribute(_("timing4"), QString::number(range.numericData4)); + if (range.numericData5 > 0) + stream.writeAttribute(_("timing5"), QString::number(range.numericData5)); + } // if (event.type == QmlDebug::Painting && range.animationCount >= 0) { // // animation frame // stream.writeAttribute(_("framerate"), QString::number(rangedEvent.frameRate)); diff --git a/plugins/qmlprofiler/qmlprofilertracefile.h b/plugins/qmlprofiler/qmlprofilertracefile.h index f5fd4dbb96d..7733c477a58 100644 --- a/plugins/qmlprofiler/qmlprofilertracefile.h +++ b/plugins/qmlprofiler/qmlprofilertracefile.h @@ -61,6 +61,13 @@ struct QmlEvent { struct Range { qint64 startTime; qint64 duration; + + // numeric data used by animations, pixmap cache, scenegraph + qint64 numericData1; + qint64 numericData2; + qint64 numericData3; + qint64 numericData4; + qint64 numericData5; }; class QmlProfilerFileReader : public QObject @@ -80,7 +87,9 @@ signals: void rangedEvent(int type, int bindingType, qint64 startTime, qint64 length, 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 error(const QString &error); private: -- cgit v1.2.3