From aaca50f705ac8f41f44991478fe11f9eb37fe0bd Mon Sep 17 00:00:00 2001 From: Ulf Hermann <ulf.hermann@qt.io> Date: Tue, 8 Nov 2016 17:26:39 +0100 Subject: [PATCH] QmlProfiler: Send loaded events in batches of about 1024 This significantly reduces the number of signals necessary when loading traces. The overhead of queueing those signals across threads was responsible for up to 80% of the time required to load a trace. Change-Id: I461a2ef9944b0be102a29f8ed6b2b3f2f59f3c0f Reviewed-by: Christian Kandeler <christian.kandeler@qt.io> --- .../qmlprofiler/qmlprofilerdatamodel.cpp | 9 +++++++++ src/plugins/qmlprofiler/qmlprofilerdatamodel.h | 1 + .../qmlprofiler/qmlprofilermodelmanager.cpp | 4 ++-- .../qmlprofiler/qmlprofilertracefile.cpp | 17 ++++++++++++----- src/plugins/qmlprofiler/qmlprofilertracefile.h | 2 +- 5 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp b/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp index 0390d493cd0..52a17f7416b 100644 --- a/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp @@ -154,6 +154,15 @@ void QmlProfilerDataModel::addEvent(const QmlEvent &event) d->eventStream << event; } +void QmlProfilerDataModel::addEvents(const QVector<QmlEvent> &events) +{ + Q_D(QmlProfilerDataModel); + for (const QmlEvent &event : events) { + d->modelManager->dispatch(event, d->eventTypes[event.typeIndex()]); + d->eventStream << event; + } +} + void QmlProfilerDataModel::clear() { Q_D(QmlProfilerDataModel); diff --git a/src/plugins/qmlprofiler/qmlprofilerdatamodel.h b/src/plugins/qmlprofiler/qmlprofilerdatamodel.h index 5bb97abea4f..4698dac409e 100644 --- a/src/plugins/qmlprofiler/qmlprofilerdatamodel.h +++ b/src/plugins/qmlprofiler/qmlprofilerdatamodel.h @@ -52,6 +52,7 @@ public: void clear(); bool isEmpty() const; void addEvent(const QmlEvent &event); + void addEvents(const QVector<QmlEvent> &events); void replayEvents(qint64 startTime, qint64 endTime, QmlProfilerModelManager::EventLoader loader) const; void finalize(); diff --git a/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp index 4c933040e64..6a236a12f9d 100644 --- a/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp +++ b/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp @@ -378,8 +378,8 @@ void QmlProfilerModelManager::load(const QString &filename) connect(reader, &QmlProfilerFileReader::notesLoaded, d->notesModel, &QmlProfilerNotesModel::setNotes); - connect(reader, &QmlProfilerFileReader::qmlEventLoaded, - d->model, &QmlProfilerDataModel::addEvent); + connect(reader, &QmlProfilerFileReader::qmlEventsLoaded, + d->model, &QmlProfilerDataModel::addEvents); connect(reader, &QmlProfilerFileReader::success, this, [this, reader]() { d->traceTime->setTime(reader->traceStart(), reader->traceEnd()); diff --git a/src/plugins/qmlprofiler/qmlprofilertracefile.cpp b/src/plugins/qmlprofiler/qmlprofilertracefile.cpp index 67188e32fa1..ec9195bbd04 100644 --- a/src/plugins/qmlprofiler/qmlprofilertracefile.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertracefile.cpp @@ -123,7 +123,7 @@ QmlProfilerFileReader::QmlProfilerFileReader(QObject *parent) : m_loadedFeatures(0) { static int meta[] = { - qRegisterMetaType<QmlEvent>(), + qRegisterMetaType<QVector<QmlEvent> >(), qRegisterMetaType<QVector<QmlEventType> >(), qRegisterMetaType<QVector<QmlNote> >() }; @@ -248,7 +248,9 @@ bool QmlProfilerFileReader::loadQzt(QIODevice *device) emit notesLoaded(m_notes); updateProgress(device); - QmlEvent event; + const int eventBufferLength = 1024; + QVector<QmlEvent> eventBuffer(eventBufferLength); + int eventBufferIndex = 0; while (!stream.atEnd()) { stream >> data; buffer.setData(qUncompress(data)); @@ -256,6 +258,7 @@ bool QmlProfilerFileReader::loadQzt(QIODevice *device) while (!buffer.atEnd()) { if (isCanceled()) return false; + QmlEvent &event = eventBuffer[eventBufferIndex]; bufferStream >> event; if (bufferStream.status() == QDataStream::Ok) { if (event.typeIndex() >= m_eventTypes.length()) { @@ -263,7 +266,6 @@ bool QmlProfilerFileReader::loadQzt(QIODevice *device) return false; } m_loadedFeatures |= (1ULL << m_eventTypes[event.typeIndex()].feature()); - emit qmlEventLoaded(event); } else if (bufferStream.status() == QDataStream::ReadPastEnd) { break; // Apparently EOF is a character so we end up here after the last event. } else if (bufferStream.status() == QDataStream::ReadCorruptData) { @@ -272,10 +274,16 @@ bool QmlProfilerFileReader::loadQzt(QIODevice *device) } else { Q_UNREACHABLE(); } + if (++eventBufferIndex == eventBufferLength) { + emit qmlEventsLoaded(eventBuffer); + eventBufferIndex = 0; + } } buffer.close(); updateProgress(device); } + eventBuffer.resize(eventBufferIndex); + emit qmlEventsLoaded(eventBuffer); emit success(); return true; } @@ -499,8 +507,7 @@ void QmlProfilerFileReader::loadEvents(QXmlStreamReader &stream) std::sort(events.begin(), events.end(), [](const QmlEvent &a, const QmlEvent &b) { return a.timestamp() < b.timestamp(); }); - foreach (const QmlEvent &event, events) - emit qmlEventLoaded(event); + emit qmlEventsLoaded(events); return; } break; diff --git a/src/plugins/qmlprofiler/qmlprofilertracefile.h b/src/plugins/qmlprofiler/qmlprofilertracefile.h index 937ec1de298..b705f07e689 100644 --- a/src/plugins/qmlprofiler/qmlprofilertracefile.h +++ b/src/plugins/qmlprofiler/qmlprofilertracefile.h @@ -62,7 +62,7 @@ public: signals: void typesLoaded(const QVector<QmlProfiler::QmlEventType> &types); void notesLoaded(const QVector<QmlProfiler::QmlNote> ¬es); - void qmlEventLoaded(const QmlProfiler::QmlEvent &event); + void qmlEventsLoaded(const QVector<QmlProfiler::QmlEvent> &event); void error(const QString &error); void success(); -- GitLab