diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2016-05-24 11:58:07 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2016-05-27 09:31:08 +0000 |
commit | 515efdb8a65dc8ba22a56a02ee6d7056f39619cb (patch) | |
tree | d984f8725ca2e9b0663b33378e5fe1d13b64fa8e /src/plugins/qmltooling/qmldbg_profiler | |
parent | 777aac3005feb01aed21df9e135d5470182bc6ce (diff) |
QmlProfiler: Send RangeData and RangeLocation only once per type
This saves time when serializing the data to be sent.
Change-Id: Ic8c534d55445934a64dd253273099194b27d98af
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/plugins/qmltooling/qmldbg_profiler')
6 files changed, 77 insertions, 45 deletions
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp index a193ddea0b..f161f988de 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp @@ -55,7 +55,7 @@ QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEngin connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling())); connect(this, SIGNAL(profilingDisabledWhileWaiting()), engine->profiler, SLOT(stopProfiling()), Qt::DirectConnection); - connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData())); + connect(this, SIGNAL(dataRequested(bool)), engine->profiler, SLOT(reportData(bool))); connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)), engine->profiler, SLOT(setTimer(QElapsedTimer))); connect(engine->profiler, @@ -68,49 +68,65 @@ QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEngin // use of QDataStream can skew results // (see tst_qqmldebugtrace::trace() benchmark) static void qQmlProfilerDataToByteArrays(const QQmlProfilerData &d, - const QQmlProfiler::LocationHash &locations, - QList<QByteArray> &messages) + QQmlProfiler::LocationHash &locations, + QList<QByteArray> &messages, + bool trackLocations) { QQmlDebugPacket ds; Q_ASSERT_X((d.messageType & (1 << 31)) == 0, Q_FUNC_INFO, "You can use at most 31 message types."); for (quint32 decodedMessageType = 0; (d.messageType >> decodedMessageType) != 0; ++decodedMessageType) { - if ((d.messageType & (1 << decodedMessageType)) == 0) - continue; - - //### using QDataStream is relatively expensive - ds << d.time << decodedMessageType << static_cast<quint32>(d.detailType); - - QQmlProfiler::Location l = locations.value(d.locationId); + if (decodedMessageType == QQmlProfilerDefinitions::RangeData + || (d.messageType & (1 << decodedMessageType)) == 0) { + continue; // RangeData is sent together with RangeLocation + } - switch (decodedMessageType) { - case QQmlProfilerDefinitions::RangeStart: - case QQmlProfilerDefinitions::RangeEnd: - break; - case QQmlProfilerDefinitions::RangeData: - ds << (l.location.sourceFile.isEmpty() ? l.url.toString() : l.location.sourceFile); - break; - case QQmlProfilerDefinitions::RangeLocation: - ds << (l.url.isEmpty() ? l.location.sourceFile : l.url.toString()) - << static_cast<qint32>(l.location.line) << static_cast<qint32>(l.location.column); - break; - default: - Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type."); - break; + if (decodedMessageType == QQmlProfilerDefinitions::RangeEnd + || decodedMessageType == QQmlProfilerDefinitions::RangeStart) { + ds << d.time << decodedMessageType << static_cast<quint32>(d.detailType); + if (trackLocations && d.locationId != 0) + ds << static_cast<qint64>(d.locationId); + } else { + auto i = locations.find(d.locationId); + if (i != locations.end()) { + ds << d.time << decodedMessageType << static_cast<quint32>(d.detailType); + ds << (i->url.isEmpty() ? i->location.sourceFile : i->url.toString()) + << static_cast<qint32>(i->location.line) + << static_cast<qint32>(i->location.column); + if (d.messageType & (1 << QQmlProfilerDefinitions::RangeData)) { + // Send both, location and data ... + if (trackLocations) + ds << static_cast<qint64>(d.locationId); + messages.append(ds.squeezedData()); + ds.clear(); + ds << d.time << QQmlProfilerDefinitions::RangeData + << static_cast<quint32>(d.detailType) + << (i->location.sourceFile.isEmpty() ? i->url.toString() : + i->location.sourceFile); + } + if (trackLocations) { + ds << static_cast<qint64>(d.locationId); + locations.erase(i); // ... so that we can erase here without missing anything. + } + } else { + // Skip RangeData and RangeLocation: We've already sent them + continue; + } } messages.append(ds.squeezedData()); ds.clear(); } } -qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages) +qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages, + bool trackLocations) { while (next != data.length()) { const QQmlProfilerData &nextData = data.at(next); if (nextData.time > until || messages.length() > s_numMessagesPerBatch) return nextData.time; - qQmlProfilerDataToByteArrays(nextData, locations, messages); + qQmlProfilerDataToByteArrays(nextData, locations, messages, trackLocations); ++next; } diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h index 7e13b6c479..96cdcd6d38 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h @@ -60,7 +60,8 @@ class QQmlProfilerAdapter : public QQmlAbstractProfilerAdapter { Q_OBJECT public: QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine); - qint64 sendMessages(qint64 until, QList<QByteArray> &messages) Q_DECL_OVERRIDE; + qint64 sendMessages(qint64 until, QList<QByteArray> &messages, + bool trackLocations) Q_DECL_OVERRIDE; public slots: void receiveData(const QVector<QQmlProfilerData> &new_data, diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp index a639cfb71e..a587188630 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp @@ -57,7 +57,7 @@ Q_QML_DEBUG_PLUGIN_LOADER(QQmlAbstractProfilerAdapter) QQmlProfilerServiceImpl::QQmlProfilerServiceImpl(QObject *parent) : QQmlConfigurableDebugService<QQmlProfilerService>(1, parent), - m_waitingForStop(false) + m_waitingForStop(false), m_useMessageTypes(false) { m_timer.start(); QQmlAbstractProfilerAdapter *quickAdapter = @@ -309,7 +309,7 @@ void QQmlProfilerServiceImpl::stopProfiling(QJSEngine *engine) m_waitingForStop = true; foreach (QQmlAbstractProfilerAdapter *profiler, reporting) - profiler->reportData(); + profiler->reportData(m_useMessageTypes); foreach (QQmlAbstractProfilerAdapter *profiler, stopping) profiler->stopProfiling(); @@ -343,7 +343,8 @@ void QQmlProfilerServiceImpl::sendMessages() m_startTimes.erase(m_startTimes.begin()); qint64 next = first->sendMessages(m_startTimes.isEmpty() ? std::numeric_limits<qint64>::max() : - m_startTimes.begin().key(), messages); + m_startTimes.begin().key(), messages, + m_useMessageTypes); if (next != -1) m_startTimes.insert(next, first); @@ -418,6 +419,8 @@ void QQmlProfilerServiceImpl::messageReceived(const QByteArray &message) disconnect(this, SIGNAL(stopFlushTimer()), &m_flushTimer, SLOT(stop())); } } + if (!stream.atEnd()) + stream >> m_useMessageTypes; // If engineId == -1 objectForId() and then the cast will return 0. if (enabled) @@ -435,14 +438,14 @@ void QQmlProfilerServiceImpl::flush() foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers) { if (profiler->isRunning()) { m_startTimes.insert(-1, profiler); - profiler->reportData(); + profiler->reportData(m_useMessageTypes); } } foreach (QQmlAbstractProfilerAdapter *profiler, m_globalProfilers) { if (profiler->isRunning()) { m_startTimes.insert(-1, profiler); - profiler->reportData(); + profiler->reportData(m_useMessageTypes); } } } diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h index 6490e77f44..42efdefd12 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h @@ -116,6 +116,7 @@ private: QElapsedTimer m_timer; QTimer m_flushTimer; bool m_waitingForStop; + bool m_useMessageTypes; QList<QQmlAbstractProfilerAdapter *> m_globalProfilers; QMultiHash<QJSEngine *, QQmlAbstractProfilerAdapter *> m_engineProfilers; diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp index 68a71a5524..c3bbb86e3a 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp +++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp @@ -58,7 +58,7 @@ QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::Execut connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling())); connect(this, SIGNAL(profilingDisabledWhileWaiting()), engine->profiler, SLOT(stopProfiling()), Qt::DirectConnection); - connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData())); + connect(this, SIGNAL(dataRequested(bool)), engine->profiler, SLOT(reportData(bool))); connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)), engine->profiler, SLOT(setTimer(QElapsedTimer))); connect(engine->profiler, SIGNAL(dataReady(QV4::Profiling::FunctionLocationHash, @@ -105,13 +105,13 @@ qint64 QV4ProfilerAdapter::finalizeMessages(qint64 until, QList<QByteArray> &mes return callNext == -1 ? memoryNext : qMin(callNext, memoryNext); } -qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages) +qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages, + bool trackLocations) { QQmlDebugPacket d; // Make it const, so that we cannot accidentally detach it. const QVector<QV4::Profiling::FunctionCallProperties> &functionCallData = m_functionCallData; - const QV4::Profiling::FunctionLocationHash &functionLocations = m_functionLocations; while (true) { while (!m_stack.isEmpty() && @@ -133,17 +133,27 @@ qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &message return finalizeMessages(until, messages, props.start, d); appendMemoryEvents(props.start, messages, d); - auto location = functionLocations.constFind(props.id); - Q_ASSERT(location != functionLocations.constEnd()); + auto location = m_functionLocations.find(props.id); d << props.start << RangeStart << Javascript; - messages.push_back(d.squeezedData()); - d.clear(); - d << props.start << RangeLocation << Javascript << location->file << location->line - << location->column; - messages.push_back(d.squeezedData()); - d.clear(); - d << props.start << RangeData << Javascript << location->name; + if (trackLocations) + d << static_cast<qint64>(props.id); + if (location != m_functionLocations.end()) { + messages.push_back(d.squeezedData()); + d.clear(); + d << props.start << RangeLocation << Javascript << location->file << location->line + << location->column; + if (trackLocations) + d << static_cast<qint64>(props.id); + messages.push_back(d.squeezedData()); + d.clear(); + d << props.start << RangeData << Javascript << location->name; + + if (trackLocations) { + d << static_cast<qint64>(props.id); + m_functionLocations.erase(location); + } + } messages.push_back(d.squeezedData()); d.clear(); m_stack.push(props.end); diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h index 968825c346..13a595f6eb 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h +++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h @@ -67,7 +67,8 @@ class QV4ProfilerAdapter : public QQmlAbstractProfilerAdapter { public: QV4ProfilerAdapter(QQmlProfilerService *service, QV4::ExecutionEngine *engine); - virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages); + virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages, + bool trackLocations) override; signals: void v4ProfilingEnabled(quint64 v4Features); |