diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2018-04-05 09:47:33 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2018-04-19 08:09:07 +0000 |
commit | 1c2e0f387f552d3fbe98050f8629c11829ec95f7 (patch) | |
tree | 1a03f9f0e5c68f384d5940f19a59017f648a820a /src/plugins/qmlprofiler/qmlprofilertracefile.cpp | |
parent | 7099f215865d90b69906dc92da77857fa0e66165 (diff) |
QmlProfiler: Move parts of model manager and trace file to Timeline
This way we can use the trace file loading and saving mechanism for
other profilers.
Change-Id: I98ec1cdde6f7abcea152cabf72e64d4e696dfa59
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
Diffstat (limited to 'src/plugins/qmlprofiler/qmlprofilertracefile.cpp')
-rw-r--r-- | src/plugins/qmlprofiler/qmlprofilertracefile.cpp | 464 |
1 files changed, 212 insertions, 252 deletions
diff --git a/src/plugins/qmlprofiler/qmlprofilertracefile.cpp b/src/plugins/qmlprofiler/qmlprofilertracefile.cpp index ec1fe76e1d..83b7023559 100644 --- a/src/plugins/qmlprofiler/qmlprofilertracefile.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertracefile.cpp @@ -24,6 +24,8 @@ ****************************************************************************/ #include "qmlprofilertracefile.h" +#include "qmlprofilernotesmodel.h" +#include "qmlprofilerconstants.h" #include <utils/qtcassert.h> @@ -114,13 +116,7 @@ static QString qmlTypeAsString(Message message, RangeType rangeType) return QString::number((int)rangeType); } - -QmlProfilerFileReader::QmlProfilerFileReader(QObject *parent) : - QObject(parent), - m_traceStart(-1), - m_traceEnd(-1), - m_future(0), - m_loadedFeatures(0) +QmlProfilerTraceFile::QmlProfilerTraceFile(QObject *parent) : Timeline::TimelineTraceFile(parent) { static int meta[] = { qRegisterMetaType<QVector<QmlEvent> >(), @@ -130,16 +126,25 @@ QmlProfilerFileReader::QmlProfilerFileReader(QObject *parent) : Q_UNUSED(meta); } -void QmlProfilerFileReader::setFuture(QFutureInterface<void> *future) +void QmlProfilerTraceFile::load(QIODevice *device) { - m_future = future; - if (m_future) { - m_future->setProgressRange(0, 1000); - m_future->setProgressValue(0); - } + const QFile *file = qobject_cast<QFile *>(device); + if (file && file->fileName().endsWith(Constants::QtdFileExtension)) + loadQtd(device); + else + loadQzt(device); +} + +void QmlProfilerTraceFile::save(QIODevice *device) +{ + const QFile *file = qobject_cast<QFile *>(device); + if (file && file->fileName().endsWith(Constants::QtdFileExtension)) + saveQtd(device); + else + saveQzt(device); } -void QmlProfilerFileReader::loadQtd(QIODevice *device) +void QmlProfilerTraceFile::loadQtd(QIODevice *device) { QXmlStreamReader stream(device); @@ -158,14 +163,13 @@ void QmlProfilerFileReader::loadQtd(QIODevice *device) else validVersion = false; if (attributes.hasAttribute(_("traceStart"))) - m_traceStart = attributes.value(_("traceStart")).toLongLong(); + setTraceStart(attributes.value(_("traceStart")).toLongLong()); if (attributes.hasAttribute(_("traceEnd"))) - m_traceEnd = attributes.value(_("traceEnd")).toLongLong(); + setTraceEnd(attributes.value(_("traceEnd")).toLongLong()); } if (elementName == _("eventData")) { loadEventTypes(stream); - emit typesLoaded(m_eventTypes); break; } @@ -176,7 +180,6 @@ void QmlProfilerFileReader::loadQtd(QIODevice *device) if (elementName == _("noteData")) { loadNotes(stream); - emit notesLoaded(m_notes); break; } @@ -194,7 +197,7 @@ void QmlProfilerFileReader::loadQtd(QIODevice *device) emit success(); } -void QmlProfilerFileReader::loadQzt(QIODevice *device) +void QmlProfilerTraceFile::loadQzt(QIODevice *device) { QDataStream stream(device); stream.setVersion(QDataStream::Qt_5_5); @@ -215,44 +218,48 @@ void QmlProfilerFileReader::loadQzt(QIODevice *device) } stream.setVersion(dataStreamVersion); - stream >> m_traceStart >> m_traceEnd; + qint64 traceStart, traceEnd; + stream >> traceStart >> traceEnd; + setTraceStart(traceStart); + setTraceEnd(traceEnd); QBuffer buffer; QDataStream bufferStream(&buffer); bufferStream.setVersion(dataStreamVersion); QByteArray data; - updateProgress(device); + setDeviceProgress(device); if (!isCanceled()) { stream >> data; buffer.setData(qUncompress(data)); buffer.open(QIODevice::ReadOnly); + QVector<QmlEventType> eventTypes; quint32 numEventTypes; bufferStream >> numEventTypes; if (numEventTypes > std::numeric_limits<int>::max()) { emit error(tr("Excessive number of event types: %1").arg(numEventTypes)); return; } - QTC_ASSERT(m_eventTypes.isEmpty(), m_eventTypes.clear()); - m_eventTypes.reserve(static_cast<int>(numEventTypes)); + eventTypes.reserve(static_cast<int>(numEventTypes)); QmlEventType type; for (int typeId = 0; typeId < static_cast<int>(numEventTypes); ++typeId) { bufferStream >> type; - m_eventTypes.append(type); + eventTypes.append(type); } buffer.close(); - emit typesLoaded(m_eventTypes); - updateProgress(device); + modelManager()->addEventTypes(eventTypes); + setDeviceProgress(device); } if (!isCanceled()) { stream >> data; buffer.setData(qUncompress(data)); buffer.open(QIODevice::ReadOnly); - bufferStream >> m_notes; + QVector<QmlNote> notes; + bufferStream >> notes; buffer.close(); - emit notesLoaded(m_notes); - updateProgress(device); + qmlNotes()->setNotes(notes); + setDeviceProgress(device); } QVector<QmlEvent> eventBuffer; @@ -264,11 +271,11 @@ void QmlProfilerFileReader::loadQzt(QIODevice *device) QmlEvent event; bufferStream >> event; if (bufferStream.status() == QDataStream::Ok) { - if (event.typeIndex() >= m_eventTypes.length()) { + if (event.typeIndex() >= traceManager()->numEventTypes()) { emit error(tr("Invalid type index %1").arg(event.typeIndex())); return; } - m_loadedFeatures |= (1ULL << m_eventTypes[event.typeIndex()].feature()); + addFeature(modelManager()->eventType(event.typeIndex()).feature()); if (event.timestamp() < 0) event.setTimestamp(0); } else if (bufferStream.status() == QDataStream::ReadPastEnd) { @@ -281,28 +288,35 @@ void QmlProfilerFileReader::loadQzt(QIODevice *device) } eventBuffer.append(event); } - emit qmlEventsLoaded(eventBuffer); + modelManager()->addEvents(eventBuffer); eventBuffer.clear(); buffer.close(); - updateProgress(device); + setDeviceProgress(device); } if (isCanceled()) { emit canceled(); } else { - emit qmlEventsLoaded(eventBuffer); + modelManager()->addEvents(eventBuffer); emit success(); } } -quint64 QmlProfilerFileReader::loadedFeatures() const +void QmlProfilerTraceFile::addEventsProgress(qint64 timestamp) +{ + addProgressValue(static_cast<float>(timestamp) / static_cast<float>(traceEnd() - traceStart()) + * ProgressEvents); +} + +void QmlProfilerTraceFile::addStageProgress(QmlProfilerTraceFile::ProgressValues stage) { - return m_loadedFeatures; + addProgressValue(stage); } -void QmlProfilerFileReader::loadEventTypes(QXmlStreamReader &stream) +void QmlProfilerTraceFile::loadEventTypes(QXmlStreamReader &stream) { QTC_ASSERT(stream.name() == _("eventData"), return); + QVector<QmlEventType> eventTypes; int typeIndex = -1; @@ -330,7 +344,7 @@ void QmlProfilerFileReader::loadEventTypes(QXmlStreamReader &stream) switch (token) { case QXmlStreamReader::StartElement: { if (elementName == _("event")) { - updateProgress(stream.device()); + setDeviceProgress(stream.device()); clearType(); const QXmlStreamAttributes attributes = stream.attributes(); @@ -407,20 +421,21 @@ void QmlProfilerFileReader::loadEventTypes(QXmlStreamReader &stream) case QXmlStreamReader::EndElement: { if (elementName == _("event")) { if (typeIndex >= 0) { - if (typeIndex >= m_eventTypes.size()) - m_eventTypes.resize(typeIndex + 1); + if (typeIndex >= eventTypes.length()) + eventTypes.resize(typeIndex + 1); QmlEventType type(messageAndRange.first, messageAndRange.second, detailType, QmlEventLocation(filename, line, column), data, displayName); - m_eventTypes[typeIndex] = type; - quint8 feature = type.feature(); + eventTypes[typeIndex] = type; + const quint8 feature = type.feature(); if (feature != MaximumProfileFeature) - m_loadedFeatures |= (1ULL << static_cast<uint>(feature)); + addFeature(feature); } break; } if (elementName == _("eventData")) { // done reading eventData + modelManager()->addEventTypes(eventTypes); return; } break; @@ -497,7 +512,7 @@ QVector<QmlEvent> EventList::finalize() return result; } -void QmlProfilerFileReader::loadEvents(QXmlStreamReader &stream) +void QmlProfilerTraceFile::loadEvents(QXmlStreamReader &stream) { QTC_ASSERT(stream.name() == _("profilerDataModel"), return); EventList events; @@ -510,7 +525,7 @@ void QmlProfilerFileReader::loadEvents(QXmlStreamReader &stream) switch (token) { case QXmlStreamReader::StartElement: { if (elementName == _("range")) { - updateProgress(stream.device()); + setDeviceProgress(stream.device()); QmlEvent event; const QXmlStreamAttributes attributes = stream.attributes(); @@ -574,7 +589,7 @@ void QmlProfilerFileReader::loadEvents(QXmlStreamReader &stream) case QXmlStreamReader::EndElement: { if (elementName == _("profilerDataModel")) { // done reading profilerDataModel - emit qmlEventsLoaded(events.finalize()); + modelManager()->addEvents(events.finalize()); return; } break; @@ -584,7 +599,7 @@ void QmlProfilerFileReader::loadEvents(QXmlStreamReader &stream) } } -void QmlProfilerFileReader::loadNotes(QXmlStreamReader &stream) +void QmlProfilerTraceFile::loadNotes(QXmlStreamReader &stream) { QmlNote currentNote; while (!stream.atEnd() && !stream.hasError() && !isCanceled()) { @@ -595,7 +610,7 @@ void QmlProfilerFileReader::loadNotes(QXmlStreamReader &stream) switch (token) { case QXmlStreamReader::StartElement: { if (elementName == _("note")) { - updateProgress(stream.device()); + setDeviceProgress(stream.device()); QXmlStreamAttributes attrs = stream.attributes(); int collapsedRow = attrs.hasAttribute(_("collapsedRow")) ? attrs.value(_("collapsedRow")).toInt() : -1; @@ -613,7 +628,7 @@ void QmlProfilerFileReader::loadNotes(QXmlStreamReader &stream) } case QXmlStreamReader::EndElement: { if (elementName == _("note")) { - m_notes.append(currentNote); + qmlNotes()->addNote(currentNote); } else if (elementName == _("noteData")) { return; } @@ -625,55 +640,7 @@ void QmlProfilerFileReader::loadNotes(QXmlStreamReader &stream) } } -void QmlProfilerFileReader::updateProgress(QIODevice *device) -{ - if (!m_future) - return; - - m_future->setProgressValue(device->pos() * 1000 / device->size()); -} - -bool QmlProfilerFileReader::isCanceled() const -{ - return m_future && m_future->isCanceled(); -} - -QmlProfilerFileWriter::QmlProfilerFileWriter(QObject *parent) : - QObject(parent), - m_startTime(0), - m_endTime(0), - m_measuredTime(0), - m_future(0) -{ -} - -void QmlProfilerFileWriter::setTraceTime(qint64 startTime, qint64 endTime, qint64 measuredTime) -{ - m_startTime = startTime; - m_endTime = endTime; - m_measuredTime = measuredTime; -} - -void QmlProfilerFileWriter::setData(const QmlProfilerModelManager *model) -{ - m_modelManager = model; -} - -void QmlProfilerFileWriter::setNotes(const QVector<QmlNote> ¬es) -{ - m_notes = notes; -} - -void QmlProfilerFileWriter::setFuture(QFutureInterface<void> *future) -{ - m_future = future; - if (m_future) { - m_future->setProgressRange(0, ProgressTotal); - m_future->setProgressValue(0); - } -} - -void QmlProfilerFileWriter::saveQtd(QIODevice *device) +void QmlProfilerTraceFile::saveQtd(QIODevice *device) { QXmlStreamWriter stream(device); @@ -683,15 +650,16 @@ void QmlProfilerFileWriter::saveQtd(QIODevice *device) stream.writeStartElement(_("trace")); stream.writeAttribute(_("version"), _(PROFILER_FILE_VERSION)); - stream.writeAttribute(_("traceStart"), QString::number(m_startTime)); - stream.writeAttribute(_("traceEnd"), QString::number(m_endTime)); + stream.writeAttribute(_("traceStart"), QString::number(traceStart())); + stream.writeAttribute(_("traceEnd"), QString::number(traceEnd())); stream.writeStartElement(_("eventData")); - stream.writeAttribute(_("totalTime"), QString::number(m_measuredTime)); - for (int typeIndex = 0, end = m_modelManager->numEventTypes(); - typeIndex < end && !isCanceled(); ++typeIndex) { + stream.writeAttribute(_("totalTime"), QString::number(measuredTime())); + const QmlProfilerModelManager *manager = modelManager(); + for (int typeIndex = 0, end = manager->numEventTypes(); typeIndex < end && !isCanceled(); + ++typeIndex) { - const QmlEventType &type = m_modelManager->eventType(typeIndex); + const QmlEventType &type = manager->eventType(typeIndex); stream.writeStartElement(_("event")); stream.writeAttribute(_("index"), QString::number(typeIndex)); @@ -734,210 +702,202 @@ void QmlProfilerFileWriter::saveQtd(QIODevice *device) } stream.writeEndElement(); } - updateProgress(ProgressTypes); + addStageProgress(ProgressTypes); stream.writeEndElement(); // eventData - if (!isCanceled()) { - stream.writeStartElement(_("profilerDataModel")); + if (isCanceled()) { + emit canceled(); + return; + } - QStack<QmlEvent> stack; - const bool success = m_modelManager->replayEvents( - -1, -1, [this, &stack, &stream](const QmlEvent &event, - const QmlEventType &type) { - if (isCanceled()) - return; + QStack<QmlEvent> stack; + qint64 lastProgressTimestamp = traceStart(); + modelManager()->replayEvents(-1, -1, [&](const QmlEvent &event, const QmlEventType &type) { + if (type.rangeType() != MaximumRangeType && event.rangeStage() == RangeStart) { + stack.push(event); + return; + } - if (type.rangeType() != MaximumRangeType && event.rangeStage() == RangeStart) { - stack.push(event); - return; - } + stream.writeStartElement(_("range")); + 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())); + } - stream.writeStartElement(_("range")); - 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())); + stream.writeAttribute(_("eventIndex"), QString::number(event.typeIndex())); + + if (type.message() == Event) { + if (type.detailType() == AnimationFrame) { + // special: animation event + stream.writeAttribute(_("framerate"), QString::number(event.number<qint32>(0))); + stream.writeAttribute(_("animationcount"), + QString::number(event.number<qint32>(1))); + stream.writeAttribute(_("thread"), QString::number(event.number<qint32>(2))); + } else if (type.detailType() == Key || type.detailType() == Mouse) { + // special: input event + stream.writeAttribute(_("type"), QString::number(event.number<qint32>(0))); + stream.writeAttribute(_("data1"), QString::number(event.number<qint32>(1))); + stream.writeAttribute(_("data2"), QString::number(event.number<qint32>(2))); } + } - stream.writeAttribute(_("eventIndex"), QString::number(event.typeIndex())); - - if (type.message() == Event) { - if (type.detailType() == AnimationFrame) { - // special: animation event - stream.writeAttribute(_("framerate"), QString::number(event.number<qint32>(0))); - stream.writeAttribute(_("animationcount"), - QString::number(event.number<qint32>(1))); - stream.writeAttribute(_("thread"), QString::number(event.number<qint32>(2))); - } else if (type.detailType() == Key || type.detailType() == Mouse) { - // special: input event - stream.writeAttribute(_("type"), QString::number(event.number<qint32>(0))); - stream.writeAttribute(_("data1"), QString::number(event.number<qint32>(1))); - stream.writeAttribute(_("data2"), QString::number(event.number<qint32>(2))); - } + // special: pixmap cache event + if (type.message() == PixmapCacheEvent) { + if (type.detailType() == PixmapSizeKnown) { + stream.writeAttribute(_("width"), QString::number(event.number<qint32>(0))); + stream.writeAttribute(_("height"), QString::number(event.number<qint32>(1))); } - // special: pixmap cache event - if (type.message() == PixmapCacheEvent) { - if (type.detailType() == PixmapSizeKnown) { - stream.writeAttribute(_("width"), QString::number(event.number<qint32>(0))); - stream.writeAttribute(_("height"), QString::number(event.number<qint32>(1))); - } - - if (type.detailType() == PixmapReferenceCountChanged - || type.detailType() == PixmapCacheCountChanged) - stream.writeAttribute(_("refCount"), QString::number(event.number<qint32>(2))); - } + if (type.detailType() == PixmapReferenceCountChanged + || type.detailType() == PixmapCacheCountChanged) + stream.writeAttribute(_("refCount"), QString::number(event.number<qint32>(2))); + } - if (type.message() == SceneGraphFrame) { - // special: scenegraph frame events - for (int i = 0; i < 5; ++i) { - qint64 number = event.number<qint64>(i); - if (number <= 0) - continue; - stream.writeAttribute(QString::fromLatin1("timing%1").arg(i + 1), - QString::number(number)); - } + if (type.message() == SceneGraphFrame) { + // special: scenegraph frame events + for (int i = 0; i < 5; ++i) { + qint64 number = event.number<qint64>(i); + if (number <= 0) + continue; + stream.writeAttribute(QString::fromLatin1("timing%1").arg(i + 1), + QString::number(number)); } + } - // special: memory allocation event - if (type.message() == MemoryAllocation) - stream.writeAttribute(_("amount"), QString::number(event.number<qint64>(0))); + // special: memory allocation event + if (type.message() == MemoryAllocation) + stream.writeAttribute(_("amount"), QString::number(event.number<qint64>(0))); - if (type.message() == DebugMessage) - stream.writeAttribute(_("text"), event.string()); + if (type.message() == DebugMessage) + stream.writeAttribute(_("text"), event.string()); - stream.writeEndElement(); + stream.writeEndElement(); - // Update the progress roughly every 4k events. It doesn't have to be precise. - if ((event.timestamp() & 0xfff) == 0) - updateProgress(event.timestamp()); - }); - if (!success) { - emit error(tr("Could not re-read events from temporary trace file. Saving failed.")); - return; + if (isProgressUpdateNeeded()) { + addEventsProgress(event.timestamp() - lastProgressTimestamp); + lastProgressTimestamp = event.timestamp(); } - + }, [&stream](){ + stream.writeStartElement(_("profilerDataModel")); + }, [this, &stream]() { stream.writeEndElement(); // profilerDataModel - } - - if (!isCanceled()) { - stream.writeStartElement(_("noteData")); - for (int noteIndex = 0; noteIndex < m_notes.size() && !isCanceled(); ++noteIndex) { - - const QmlNote ¬e = m_notes[noteIndex]; - stream.writeStartElement(_("note")); - stream.writeAttribute(_("startTime"), QString::number(note.startTime())); - stream.writeAttribute(_("duration"), QString::number(note.duration())); - stream.writeAttribute(_("eventIndex"), QString::number(note.typeIndex())); - stream.writeAttribute(_("collapsedRow"), QString::number(note.collapsedRow())); - stream.writeCharacters(note.text()); - stream.writeEndElement(); // note + if (!isCanceled()) { + stream.writeStartElement(_("noteData")); + const QVector<QmlNote> ¬es = qmlNotes()->notes(); + for (int noteIndex = 0; noteIndex < notes.length() && !isCanceled(); ++noteIndex) { + const QmlNote ¬e = notes[noteIndex]; + stream.writeStartElement(_("note")); + stream.writeAttribute(_("startTime"), QString::number(note.startTime())); + stream.writeAttribute(_("duration"), QString::number(note.duration())); + stream.writeAttribute(_("eventIndex"), QString::number(note.typeIndex())); + stream.writeAttribute(_("collapsedRow"), QString::number(note.collapsedRow())); + stream.writeCharacters(note.text()); + stream.writeEndElement(); // note + } + stream.writeEndElement(); // noteData + addStageProgress(ProgressNotes); } - stream.writeEndElement(); // noteData - updateProgress(ProgressNotes); - } - - stream.writeEndElement(); // trace - stream.writeEndDocument(); - if (isCanceled()) { - emit canceled(); - } else if (stream.hasError()) { - emit error(tr("Error writing trace file.")); - } else { - emit success(); - } + stream.writeEndElement(); // trace + stream.writeEndDocument(); + + if (isCanceled()) + emit canceled(); + else if (stream.hasError()) + emit error(tr("Error writing trace file.")); + else + emit success(); + }, [this](const QString &message) { + emit error(tr("Could not re-read events from temporary trace file: %s\nSaving failed.") + .arg(message)); + }, future()); } -void QmlProfilerFileWriter::saveQzt(QFile *file) +void QmlProfilerTraceFile::saveQzt(QIODevice *device) { - QDataStream stream(file); + QDataStream stream(device); stream.setVersion(QDataStream::Qt_5_5); stream << QByteArray("QMLPROFILER"); stream << static_cast<qint32>(QDataStream::Qt_DefaultCompiledVersion); stream.setVersion(QDataStream::Qt_DefaultCompiledVersion); - stream << m_startTime << m_endTime; + stream << traceStart() << traceEnd(); QBuffer buffer; QDataStream bufferStream(&buffer); buffer.open(QIODevice::WriteOnly); if (!isCanceled()) { - const int numEventTypes = m_modelManager->numEventTypes(); + const QmlProfilerModelManager *manager = modelManager(); + const int numEventTypes = manager->numEventTypes(); bufferStream << static_cast<quint32>(numEventTypes); for (int typeId = 0; typeId < numEventTypes; ++typeId) - bufferStream << m_modelManager->eventType(typeId); + bufferStream << manager->eventType(typeId); stream << qCompress(buffer.data()); buffer.close(); buffer.buffer().clear(); - updateProgress(ProgressTypes); + addStageProgress(ProgressTypes); } if (!isCanceled()) { buffer.open(QIODevice::WriteOnly); - bufferStream << m_notes; + bufferStream << qmlNotes()->notes(); stream << qCompress(buffer.data()); buffer.close(); buffer.buffer().clear(); - updateProgress(ProgressNotes); - } - - if (!isCanceled()) { - buffer.open(QIODevice::WriteOnly); - const bool success = m_modelManager->replayEvents( - -1, -1, [this, &stream, &buffer, &bufferStream](const QmlEvent &event, - const QmlEventType &type) { - Q_UNUSED(type); - bufferStream << event; - // 32MB buffer should be plenty for efficient compression - if (buffer.data().length() > (1 << 25)) { - stream << qCompress(buffer.data()); - buffer.close(); - buffer.buffer().clear(); - if (isCanceled()) - return; - buffer.open(QIODevice::WriteOnly); - updateProgress(event.timestamp()); - } - }); - if (!success) { - emit error(tr("Could not re-read events from temporary trace file. Saving failed.")); - return; - } + addStageProgress(ProgressNotes); } if (isCanceled()) { emit canceled(); - } else { - stream << qCompress(buffer.data()); - buffer.close(); - buffer.buffer().clear(); - updateProgress(m_endTime); - emit success(); + return; } + + qint64 lastProgressTimestamp = traceStart(); + modelManager()->replayEvents(-1, -1, [&](const QmlEvent &event, const QmlEventType &type) { + Q_UNUSED(type); + bufferStream << event; + // 32MB buffer should be plenty for efficient compression + if (buffer.data().length() > (1 << 25)) { + stream << qCompress(buffer.data()); + buffer.close(); + buffer.buffer().clear(); + buffer.open(QIODevice::WriteOnly); + if (isProgressUpdateNeeded()) { + addEventsProgress(event.timestamp() - lastProgressTimestamp); + lastProgressTimestamp = event.timestamp(); + } + } + }, [&]() { + buffer.open(QIODevice::WriteOnly); + }, [&]() { + if (isCanceled()) { + emit canceled(); + } else { + stream << qCompress(buffer.data()); + buffer.close(); + buffer.buffer().clear(); + addEventsProgress(traceEnd() - lastProgressTimestamp); + emit success(); + } + }, [this](const QString &message) { + emit error(tr("Could not re-read events from temporary trace file: %s\nSaving failed.") + .arg(message)); + }, future()); } -void QmlProfilerFileWriter::updateProgress(qint64 timestamp) +QmlProfilerModelManager *QmlProfilerTraceFile::modelManager() { - if (!m_future) - return; - - if (timestamp < 0) { - m_future->setProgressValue(m_future->progressValue() - timestamp); - } else { - m_future->setProgressValue(m_future->progressValue() - + float(m_endTime - timestamp) / float(m_endTime - m_startTime) - * ProgressEvents); - } + return static_cast<QmlProfilerModelManager *>(traceManager()); } -bool QmlProfilerFileWriter::isCanceled() const +QmlProfilerNotesModel *QmlProfilerTraceFile::qmlNotes() { - return m_future && m_future->isCanceled(); + return static_cast<QmlProfilerNotesModel *>(notes()); } } // namespace Internal |