diff options
Diffstat (limited to 'src/plugins/qmltooling/qmldbg_profiler')
6 files changed, 126 insertions, 98 deletions
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp index a193ddea0b..90e817e2fc 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp @@ -48,69 +48,86 @@ QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEngin next(0) { setService(service); - engine->enableProfiler(); - connect(this, SIGNAL(profilingEnabled(quint64)), engine->profiler, SLOT(startProfiling(quint64))); - connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)), - engine->profiler, SLOT(startProfiling(quint64)), Qt::DirectConnection); - 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(referenceTimeKnown(QElapsedTimer)), - engine->profiler, SLOT(setTimer(QElapsedTimer))); - connect(engine->profiler, - SIGNAL(dataReady(QVector<QQmlProfilerData>,QQmlProfiler::LocationHash)), - this, - SLOT(receiveData(QVector<QQmlProfilerData>,QQmlProfiler::LocationHash))); + engine->profiler = new QQmlProfiler; + connect(this, &QQmlProfilerAdapter::profilingEnabled, + engine->profiler, &QQmlProfiler::startProfiling); + connect(this, &QQmlAbstractProfilerAdapter::profilingEnabledWhileWaiting, + engine->profiler, &QQmlProfiler::startProfiling, Qt::DirectConnection); + connect(this, &QQmlAbstractProfilerAdapter::profilingDisabled, + engine->profiler, &QQmlProfiler::stopProfiling); + connect(this, &QQmlAbstractProfilerAdapter::profilingDisabledWhileWaiting, + engine->profiler, &QQmlProfiler::stopProfiling, Qt::DirectConnection); + connect(this, &QQmlAbstractProfilerAdapter::dataRequested, + engine->profiler, &QQmlProfiler::reportData); + connect(this, &QQmlAbstractProfilerAdapter::referenceTimeKnown, + engine->profiler, &QQmlProfiler::setTimer); + connect(engine->profiler, &QQmlProfiler::dataReady, + this, &QQmlProfilerAdapter::receiveData); } // convert to QByteArrays that can be sent to the debug client // 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 << int(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..1fee5c389f 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h @@ -60,9 +60,9 @@ 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, const QQmlProfiler::LocationHash &locations); diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp index e17722bb3d..dba2fd3cc3 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); @@ -408,16 +409,20 @@ void QQmlProfilerServiceImpl::messageReceived(const QByteArray &message) if (!stream.atEnd()) { stream >> flushInterval; m_flushTimer.setInterval(flushInterval); + auto timerStart = static_cast<void(QTimer::*)()>(&QTimer::start); if (flushInterval > 0) { - connect(&m_flushTimer, SIGNAL(timeout()), this, SLOT(flush())); - connect(this, SIGNAL(startFlushTimer()), &m_flushTimer, SLOT(start())); - connect(this, SIGNAL(stopFlushTimer()), &m_flushTimer, SLOT(stop())); + connect(&m_flushTimer, &QTimer::timeout, this, &QQmlProfilerServiceImpl::flush); + connect(this, &QQmlProfilerServiceImpl::startFlushTimer, &m_flushTimer, timerStart); + connect(this, &QQmlProfilerServiceImpl::stopFlushTimer, &m_flushTimer, &QTimer::stop); } else { - disconnect(&m_flushTimer, SIGNAL(timeout()), this, SLOT(flush())); - disconnect(this, SIGNAL(startFlushTimer()), &m_flushTimer, SLOT(start())); - disconnect(this, SIGNAL(stopFlushTimer()), &m_flushTimer, SLOT(stop())); + disconnect(&m_flushTimer, &QTimer::timeout, this, &QQmlProfilerServiceImpl::flush); + disconnect(this, &QQmlProfilerServiceImpl::startFlushTimer, &m_flushTimer, timerStart); + disconnect(this, &QQmlProfilerServiceImpl::stopFlushTimer, + &m_flushTimer, &QTimer::stop); } } + if (!stream.atEnd()) + stream >> m_useMessageTypes; // If engineId == -1 objectForId() and then the cast will return 0. if (enabled) @@ -448,7 +453,7 @@ void QQmlProfilerServiceImpl::flush() } foreach (QQmlAbstractProfilerAdapter *profiler, reporting) - profiler->reportData(); + profiler->reportData(m_useMessageTypes); } QT_END_NAMESPACE diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h index 6490e77f44..bbfc32b681 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h @@ -99,9 +99,6 @@ signals: void startFlushTimer(); void stopFlushTimer(); -private slots: - void flush(); - protected: virtual void stateAboutToBeChanged(State state) Q_DECL_OVERRIDE; virtual void messageReceived(const QByteArray &) Q_DECL_OVERRIDE; @@ -112,10 +109,12 @@ private: void sendMessages(); void addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QJSEngine *engine); void removeProfilerFromStartTimes(const QQmlAbstractProfilerAdapter *profiler); + void flush(); 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..eae5e0a795 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp +++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp @@ -46,27 +46,26 @@ QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::Execut m_functionCallPos(0), m_memoryPos(0) { setService(service); - engine->enableProfiler(); - connect(this, SIGNAL(profilingEnabled(quint64)), - this, SLOT(forwardEnabled(quint64))); - connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)), - this, SLOT(forwardEnabledWhileWaiting(quint64)), Qt::DirectConnection); - connect(this, SIGNAL(v4ProfilingEnabled(quint64)), - engine->profiler, SLOT(startProfiling(quint64))); - connect(this, SIGNAL(v4ProfilingEnabledWhileWaiting(quint64)), - engine->profiler, SLOT(startProfiling(quint64)), Qt::DirectConnection); - connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling())); - connect(this, SIGNAL(profilingDisabledWhileWaiting()), engine->profiler, SLOT(stopProfiling()), + engine->setProfiler(new QV4::Profiling::Profiler(engine)); + connect(this, &QQmlAbstractProfilerAdapter::profilingEnabled, + this, &QV4ProfilerAdapter::forwardEnabled); + connect(this, &QQmlAbstractProfilerAdapter::profilingEnabledWhileWaiting, + this, &QV4ProfilerAdapter::forwardEnabledWhileWaiting, Qt::DirectConnection); + connect(this, &QV4ProfilerAdapter::v4ProfilingEnabled, + engine->profiler(), &QV4::Profiling::Profiler::startProfiling); + connect(this, &QV4ProfilerAdapter::v4ProfilingEnabledWhileWaiting, + engine->profiler(), &QV4::Profiling::Profiler::startProfiling, Qt::DirectConnection); + connect(this, &QQmlAbstractProfilerAdapter::profilingDisabled, + engine->profiler(), &QV4::Profiling::Profiler::stopProfiling); + connect(this, &QQmlAbstractProfilerAdapter::profilingDisabledWhileWaiting, + engine->profiler(), &QV4::Profiling::Profiler::stopProfiling, Qt::DirectConnection); - connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData())); - connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)), - engine->profiler, SLOT(setTimer(QElapsedTimer))); - connect(engine->profiler, SIGNAL(dataReady(QV4::Profiling::FunctionLocationHash, - QVector<QV4::Profiling::FunctionCallProperties>, - QVector<QV4::Profiling::MemoryAllocationProperties>)), - this, SLOT(receiveData(QV4::Profiling::FunctionLocationHash, - QVector<QV4::Profiling::FunctionCallProperties>, - QVector<QV4::Profiling::MemoryAllocationProperties>))); + connect(this, &QQmlAbstractProfilerAdapter::dataRequested, + engine->profiler(), &QV4::Profiling::Profiler::reportData); + connect(this, &QQmlAbstractProfilerAdapter::referenceTimeKnown, + engine->profiler(), &QV4::Profiling::Profiler::setTimer); + connect(engine->profiler(), &QV4::Profiling::Profiler::dataReady, + this, &QV4ProfilerAdapter::receiveData); } qint64 QV4ProfilerAdapter::appendMemoryEvents(qint64 until, QList<QByteArray> &messages, @@ -77,7 +76,7 @@ qint64 QV4ProfilerAdapter::appendMemoryEvents(qint64 until, QList<QByteArray> &m while (memoryData.length() > m_memoryPos && memoryData[m_memoryPos].timestamp <= until) { const QV4::Profiling::MemoryAllocationProperties &props = memoryData[m_memoryPos]; - d << props.timestamp << MemoryAllocation << props.type << props.size; + d << props.timestamp << int(MemoryAllocation) << int(props.type) << props.size; ++m_memoryPos; messages.append(d.squeezedData()); d.clear(); @@ -105,13 +104,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() && @@ -121,7 +120,7 @@ qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &message return finalizeMessages(until, messages, m_stack.top(), d); appendMemoryEvents(m_stack.top(), messages, d); - d << m_stack.pop() << RangeEnd << Javascript; + d << m_stack.pop() << int(RangeEnd) << int(Javascript); messages.append(d.squeezedData()); d.clear(); } @@ -133,17 +132,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()); - - 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; + auto location = m_functionLocations.find(props.id); + + d << props.start << int(RangeStart) << int(Javascript); + if (trackLocations) + d << static_cast<qint64>(props.id); + if (location != m_functionLocations.end()) { + messages.push_back(d.squeezedData()); + d.clear(); + d << props.start << int(RangeLocation) << int(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 << int(RangeData) << int(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..5d5b83f7ca 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h +++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h @@ -67,20 +67,16 @@ 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); - void v4ProfilingEnabledWhileWaiting(quint64 v4Features); - -public slots: void receiveData(const QV4::Profiling::FunctionLocationHash &, const QVector<QV4::Profiling::FunctionCallProperties> &, const QVector<QV4::Profiling::MemoryAllocationProperties> &); -private slots: - void forwardEnabled(quint64 features); - void forwardEnabledWhileWaiting(quint64 features); +signals: + void v4ProfilingEnabled(quint64 v4Features); + void v4ProfilingEnabledWhileWaiting(quint64 v4Features); private: QV4::Profiling::FunctionLocationHash m_functionLocations; @@ -92,6 +88,8 @@ private: qint64 appendMemoryEvents(qint64 until, QList<QByteArray> &messages, QQmlDebugPacket &d); qint64 finalizeMessages(qint64 until, QList<QByteArray> &messages, qint64 callNext, QQmlDebugPacket &d); + void forwardEnabled(quint64 features); + void forwardEnabledWhileWaiting(quint64 features); static quint64 translateFeatures(quint64 qmlFeatures); }; |