diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2016-04-28 16:13:16 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2016-05-23 12:31:44 +0000 |
commit | 4a1e5a637a08299bd94428fba233d985a63f4675 (patch) | |
tree | 95200030f1509d6e95b4dea682ba3f44187cadb9 /src/plugins/qmlprofiler/qmlprofilertracefile.cpp | |
parent | dd87df7e5d338663283cfd1fa24b7c069a580167 (diff) | |
download | qt-creator-4a1e5a637a08299bd94428fba233d985a63f4675.tar.gz |
QmlProfiler: Drive event loading from the model manager
We want to get rid of the big master list of QmlEvent in
QmlProfilerDataModel, as that gets very large for longer traces. In
order to reduce the dependencies on that list we load the events on the
fly into the child models while they are being received, rather than
having the child models query QmlProfilerDataModel for the event list
later.
As the trace client so far only emitted rangedEvent() for complete
ranges we run into problems with models that need their events sorted.
The rangedEvent() signals were sorted by end time, rather than start
time which makes it inconvenient to analyze them in a stack based way,
for aggregation. This is solved by passing on all the details from the
trace client to the models, with the QmlProfilerDataModel aggregating
the type information before having the events dispatched to the child
models.
Change-Id: I5831a20551f21cf91e27d298a709f604ebd96c3e
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/plugins/qmlprofiler/qmlprofilertracefile.cpp')
-rw-r--r-- | src/plugins/qmlprofiler/qmlprofilertracefile.cpp | 107 |
1 files changed, 64 insertions, 43 deletions
diff --git a/src/plugins/qmlprofiler/qmlprofilertracefile.cpp b/src/plugins/qmlprofiler/qmlprofilertracefile.cpp index ca15d28eb6..e726448303 100644 --- a/src/plugins/qmlprofiler/qmlprofilertracefile.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertracefile.cpp @@ -31,6 +31,7 @@ #include <QStringList> #include <QXmlStreamReader> #include <QXmlStreamWriter> +#include <QStack> #include <QDebug> namespace QmlProfiler { @@ -181,6 +182,9 @@ bool QmlProfilerFileReader::load(QIODevice *device) emit error(tr("Error while parsing trace data file: %1").arg(stream.errorString())); return false; } else { + std::sort(m_events.begin(), m_events.end(), [](const QmlEvent &a, const QmlEvent &b) { + return a.timestamp() < b.timestamp(); + }); emit success(); return true; } @@ -370,46 +374,53 @@ void QmlProfilerFileReader::loadEvents(QXmlStreamReader &stream) } event.setTimestamp(attributes.value(_("startTime")).toLongLong()); - if (attributes.hasAttribute(_("duration"))) - event.setDuration(attributes.value(_("duration")).toLongLong()); - - // attributes for special events - if (attributes.hasAttribute(_("framerate"))) - event.setNumber<qint32>(0, attributes.value(_("framerate")).toInt()); - if (attributes.hasAttribute(_("animationcount"))) - event.setNumber<qint32>(1, attributes.value(_("animationcount")).toInt()); - if (attributes.hasAttribute(_("thread"))) - event.setNumber<qint32>(2, attributes.value(_("thread")).toInt()); - if (attributes.hasAttribute(_("width"))) - event.setNumber<qint32>(0, attributes.value(_("width")).toInt()); - if (attributes.hasAttribute(_("height"))) - event.setNumber<qint32>(1, attributes.value(_("height")).toInt()); - if (attributes.hasAttribute(_("refCount"))) - event.setNumber<qint32>(2, attributes.value(_("refCount")).toInt()); - if (attributes.hasAttribute(_("amount"))) - event.setNumber<qint64>(0, attributes.value(_("amount")).toLongLong()); - if (attributes.hasAttribute(_("timing1"))) - event.setNumber<qint64>(0, attributes.value(_("timing1")).toLongLong()); - if (attributes.hasAttribute(_("timing2"))) - event.setNumber<qint64>(1, attributes.value(_("timing2")).toLongLong()); - if (attributes.hasAttribute(_("timing3"))) - event.setNumber<qint64>(2, attributes.value(_("timing3")).toLongLong()); - if (attributes.hasAttribute(_("timing4"))) - event.setNumber<qint64>(3, attributes.value(_("timing4")).toLongLong()); - if (attributes.hasAttribute(_("timing5"))) - event.setNumber<qint64>(4, attributes.value(_("timing5")).toLongLong()); - if (attributes.hasAttribute(_("type"))) - event.setNumber<qint32>(0, attributes.value(_("type")).toInt()); - if (attributes.hasAttribute(_("data1"))) - event.setNumber<qint32>(1, attributes.value(_("data1")).toInt()); - if (attributes.hasAttribute(_("data2"))) - event.setNumber<qint32>(2, attributes.value(_("data2")).toInt()); - if (attributes.hasAttribute(_("text"))) - event.setString(attributes.value(_("text")).toString()); - event.setTypeIndex(attributes.value(_("eventIndex")).toInt()); - m_events.append(event); + if (attributes.hasAttribute(_("duration"))) { + event.setRangeStage(RangeStart); + m_events.append(event); + QmlEvent rangeEnd(event); + rangeEnd.setRangeStage(RangeEnd); + rangeEnd.setTimestamp(event.timestamp() + + attributes.value(_("duration")).toLongLong()); + m_events.append(rangeEnd); + } else { + // attributes for special events + if (attributes.hasAttribute(_("framerate"))) + event.setNumber<qint32>(0, attributes.value(_("framerate")).toInt()); + if (attributes.hasAttribute(_("animationcount"))) + event.setNumber<qint32>(1, attributes.value(_("animationcount")).toInt()); + if (attributes.hasAttribute(_("thread"))) + event.setNumber<qint32>(2, attributes.value(_("thread")).toInt()); + if (attributes.hasAttribute(_("width"))) + event.setNumber<qint32>(0, attributes.value(_("width")).toInt()); + if (attributes.hasAttribute(_("height"))) + event.setNumber<qint32>(1, attributes.value(_("height")).toInt()); + if (attributes.hasAttribute(_("refCount"))) + event.setNumber<qint32>(2, attributes.value(_("refCount")).toInt()); + if (attributes.hasAttribute(_("amount"))) + event.setNumber<qint64>(0, attributes.value(_("amount")).toLongLong()); + if (attributes.hasAttribute(_("timing1"))) + event.setNumber<qint64>(0, attributes.value(_("timing1")).toLongLong()); + if (attributes.hasAttribute(_("timing2"))) + event.setNumber<qint64>(1, attributes.value(_("timing2")).toLongLong()); + if (attributes.hasAttribute(_("timing3"))) + event.setNumber<qint64>(2, attributes.value(_("timing3")).toLongLong()); + if (attributes.hasAttribute(_("timing4"))) + event.setNumber<qint64>(3, attributes.value(_("timing4")).toLongLong()); + if (attributes.hasAttribute(_("timing5"))) + event.setNumber<qint64>(4, attributes.value(_("timing5")).toLongLong()); + if (attributes.hasAttribute(_("type"))) + event.setNumber<qint32>(0, attributes.value(_("type")).toInt()); + if (attributes.hasAttribute(_("data1"))) + event.setNumber<qint32>(1, attributes.value(_("data1")).toInt()); + if (attributes.hasAttribute(_("data2"))) + event.setNumber<qint32>(2, attributes.value(_("data2")).toInt()); + if (attributes.hasAttribute(_("text"))) + event.setString(attributes.value(_("text")).toString()); + + m_events.append(event); + } } break; } @@ -584,19 +595,29 @@ void QmlProfilerFileWriter::save(QIODevice *device) stream.writeStartElement(_("profilerDataModel")); + QStack<QmlEvent> stack; for (int rangeIndex = 0; rangeIndex < m_events.size(); ++rangeIndex) { if (isCanceled()) return; const QmlEvent &event = m_events[rangeIndex]; + const QmlEventType &type = m_eventTypes[event.typeIndex()]; + if (type.rangeType != MaximumRangeType && event.rangeStage() == RangeStart) { + stack.push(event); + continue; + } stream.writeStartElement(_("range")); - stream.writeAttribute(_("startTime"), QString::number(event.timestamp())); - if (event.duration() > 0) // no need to store duration of instantaneous events - stream.writeAttribute(_("duration"), QString::number(event.duration())); - stream.writeAttribute(_("eventIndex"), QString::number(event.typeIndex())); + if (type.rangeType != MaximumRangeType && event.rangeStage() == RangeEnd) { + QmlEvent start = stack.pop(); + stream.writeAttribute(_("startTime"), QString::number(start.timestamp())); + stream.writeAttribute(_("duration"), + QString::number(event.timestamp() - start.timestamp())); + } else { + stream.writeAttribute(_("startTime"), QString::number(event.timestamp())); + } - const QmlEventType &type = m_eventTypes[event.typeIndex()]; + stream.writeAttribute(_("eventIndex"), QString::number(event.typeIndex())); if (type.message == Event) { if (type.detailType == AnimationFrame) { |