QmlProfiler: load and save extra data

Change-Id: I97a9bc3c86b330015d1c40850eabbcfa37088521
Reviewed-by: Kai Koehne <kai.koehne@digia.com>
This commit is contained in:
Christiaan Janssen
2013-07-09 12:28:06 +02:00
committed by Kai Koehne
parent bf467e258b
commit 483e607f27
6 changed files with 124 additions and 16 deletions

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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));
}

View File

@@ -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,int>(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<QmlProfilerSimpleModel::Q
m_qmlEvents.insert(hashStr, e);
}
Range r = { event.startTime, event.duration, };
Range r = { event.startTime, event.duration, event.numericData1, event.numericData2, event.numericData3, event.numericData4, event.numericData5 };
m_ranges.append(QPair<Range, QString>(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));

View File

@@ -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: