aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2016-05-24 11:58:07 +0200
committerUlf Hermann <ulf.hermann@qt.io>2016-05-27 09:31:08 +0000
commit515efdb8a65dc8ba22a56a02ee6d7056f39619cb (patch)
treed984f8725ca2e9b0663b33378e5fe1d13b64fa8e /src
parent777aac3005feb01aed21df9e135d5470182bc6ce (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')
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp68
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h3
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp13
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h1
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp34
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h3
-rw-r--r--src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp8
-rw-r--r--src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h2
-rw-r--r--src/qml/debugger/qqmlabstractprofileradapter_p.h6
-rw-r--r--src/qml/debugger/qqmlprofiler.cpp18
-rw-r--r--src/qml/debugger/qqmlprofiler_p.h28
-rw-r--r--src/qml/jsruntime/qv4profiling.cpp17
-rw-r--r--src/qml/jsruntime/qv4profiling_p.h49
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp5
-rw-r--r--src/qmldebug/qqmlprofilerclient.cpp21
-rw-r--r--src/qmldebug/qqmlprofilerclient_p_p.h8
-rw-r--r--src/quick/util/qquickprofiler.cpp3
-rw-r--r--src/quick/util/qquickprofiler_p.h2
18 files changed, 200 insertions, 89 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);
diff --git a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp
index 9a2afd367d..bebf8806c6 100644
--- a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp
@@ -61,8 +61,8 @@ QQuickProfilerAdapter::QQuickProfilerAdapter(QObject *parent) :
QQuickProfiler::s_instance, SLOT(stopProfilingImpl()), Qt::DirectConnection);
connect(this, SIGNAL(profilingDisabledWhileWaiting()),
QQuickProfiler::s_instance, SLOT(stopProfilingImpl()), Qt::DirectConnection);
- connect(this, SIGNAL(dataRequested()),
- QQuickProfiler::s_instance, SLOT(reportDataImpl()), Qt::DirectConnection);
+ connect(this, SIGNAL(dataRequested(bool)),
+ QQuickProfiler::s_instance, SLOT(reportDataImpl(bool)), Qt::DirectConnection);
connect(QQuickProfiler::s_instance, SIGNAL(dataReady(QVector<QQuickProfilerData>)),
this, SLOT(receiveData(QVector<QQuickProfilerData>)), Qt::DirectConnection);
}
@@ -150,8 +150,10 @@ static void qQuickProfilerDataToByteArrays(const QQuickProfilerData &data,
}
}
-qint64 QQuickProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
+qint64 QQuickProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages,
+ bool trackLocations)
{
+ Q_UNUSED(trackLocations);
while (next < m_data.size()) {
if (m_data[next].time <= until && messages.length() <= s_numMessagesPerBatch)
qQuickProfilerDataToByteArrays(m_data[next++], messages);
diff --git a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h
index 0983561d2c..f1ba411ac5 100644
--- a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h
+++ b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h
@@ -61,7 +61,7 @@ class QQuickProfilerAdapter : public QQmlAbstractProfilerAdapter {
public:
QQuickProfilerAdapter(QObject *parent = 0);
~QQuickProfilerAdapter();
- qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
+ qint64 sendMessages(qint64 until, QList<QByteArray> &messages, bool trackLocations) override;
public slots:
void receiveData(const QVector<QQuickProfilerData> &new_data);
diff --git a/src/qml/debugger/qqmlabstractprofileradapter_p.h b/src/qml/debugger/qqmlabstractprofileradapter_p.h
index 1104608055..8820c4311a 100644
--- a/src/qml/debugger/qqmlabstractprofileradapter_p.h
+++ b/src/qml/debugger/qqmlabstractprofileradapter_p.h
@@ -71,13 +71,13 @@ public:
virtual ~QQmlAbstractProfilerAdapter() {}
void setService(QQmlProfilerService *new_service) { service = new_service; }
- virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages) = 0;
+ virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages, bool trackLocations) = 0;
void startProfiling(quint64 features);
void stopProfiling();
- void reportData() { emit dataRequested(); }
+ void reportData(bool trackLocations) { emit dataRequested(trackLocations); }
void stopWaiting() { waiting = false; }
void startWaiting() { waiting = true; }
@@ -94,7 +94,7 @@ signals:
void profilingDisabled();
void profilingDisabledWhileWaiting();
- void dataRequested();
+ void dataRequested(bool trackLocations);
void referenceTimeKnown(const QElapsedTimer &timer);
protected:
diff --git a/src/qml/debugger/qqmlprofiler.cpp b/src/qml/debugger/qqmlprofiler.cpp
index 629d5cb7b8..ffba731b13 100644
--- a/src/qml/debugger/qqmlprofiler.cpp
+++ b/src/qml/debugger/qqmlprofiler.cpp
@@ -59,19 +59,21 @@ void QQmlProfiler::startProfiling(quint64 features)
void QQmlProfiler::stopProfiling()
{
featuresEnabled = false;
- reportData();
+ reportData(true);
+ m_locations.clear();
}
-void QQmlProfiler::reportData()
+void QQmlProfiler::reportData(bool trackLocations)
{
LocationHash resolved;
resolved.reserve(m_locations.size());
- for (auto it = m_locations.constBegin(), end = m_locations.constEnd(); it != end; ++it)
- resolved.insert(it.key(), it.value());
-
- // This unrefs all the objects. We have to make sure we do this in the GUI thread. Also, it's
- // a good idea to release the memory before creating the packets to be sent.
- m_locations.clear();
+ for (auto it = m_locations.begin(), end = m_locations.end(); it != end; ++it) {
+ if (!trackLocations || !it->sent) {
+ resolved.insert(it.key(), it.value());
+ if (trackLocations)
+ it->sent = true;
+ }
+ }
QVector<QQmlProfilerData> data;
data.swap(m_data);
diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h
index 1380599fb7..60851ac444 100644
--- a/src/qml/debugger/qqmlprofiler_p.h
+++ b/src/qml/debugger/qqmlprofiler_p.h
@@ -146,26 +146,27 @@ public:
// Unfortunately we have to resolve the locations right away because the QML context might not
// be available anymore when we send the data.
struct RefLocation : public Location {
- RefLocation() : Location(), locationType(MaximumRangeType), ref(nullptr)
+ RefLocation() : Location(), locationType(MaximumRangeType), ref(nullptr), sent(false)
{}
RefLocation(QQmlBinding *binding, QV4::FunctionObject *function) :
Location(function->sourceLocation()), locationType(Binding),
- ref(new BindingRefCount(binding), QQmlRefPointer<QQmlRefCount>::Adopt)
+ ref(new BindingRefCount(binding), QQmlRefPointer<QQmlRefCount>::Adopt), sent(false)
{}
RefLocation(QQmlCompiledData *ref, const QUrl &url, const QV4::CompiledData::Object *obj,
const QString &type) :
Location(QQmlSourceLocation(type, obj->location.line, obj->location.column), url),
- locationType(Creating), ref(ref)
+ locationType(Creating), ref(ref), sent(false)
{}
RefLocation(QQmlBoundSignalExpression *ref) :
- Location(ref->sourceLocation()), locationType(HandlingSignal), ref(ref)
+ Location(ref->sourceLocation()), locationType(HandlingSignal), ref(ref), sent(false)
{}
RefLocation(QQmlDataBlob *ref) :
- Location(QQmlSourceLocation(), ref->url()), locationType(Compiling), ref(ref)
+ Location(QQmlSourceLocation(), ref->url()), locationType(Compiling), ref(ref),
+ sent(false)
{}
bool isValid() const
@@ -175,6 +176,7 @@ public:
RangeType locationType;
QQmlRefPointer<QQmlRefCount> ref;
+ bool sent;
};
typedef QHash<quintptr, Location> LocationHash;
@@ -217,11 +219,6 @@ public:
location = RefLocation(expression);
}
- void startCreating()
- {
- m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeStart, Creating));
- }
-
void startCreating(const QV4::CompiledData::Object *obj)
{
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
@@ -233,10 +230,6 @@ public:
const QUrl &url, const QString &type)
{
quintptr locationId(id(obj));
- m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
- (1 << RangeLocation | 1 << RangeData),
- Creating, locationId));
-
RefLocation &location = m_locations[locationId];
if (!location.isValid())
location = RefLocation(ref, url, obj, type);
@@ -261,7 +254,7 @@ public:
public slots:
void startProfiling(quint64 features);
void stopProfiling();
- void reportData();
+ void reportData(bool trackLocations);
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
signals:
@@ -363,9 +356,10 @@ private:
class QQmlObjectCreationProfiler {
public:
- QQmlObjectCreationProfiler(QQmlProfiler *profiler) : profiler(profiler)
+ QQmlObjectCreationProfiler(QQmlProfiler *profiler, const QV4::CompiledData::Object *obj)
+ : profiler(profiler)
{
- Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler, startCreating());
+ Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler, startCreating(obj));
}
~QQmlObjectCreationProfiler()
diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp
index 72475c5416..349ec48e06 100644
--- a/src/qml/jsruntime/qv4profiling.cpp
+++ b/src/qml/jsruntime/qv4profiling.cpp
@@ -78,7 +78,8 @@ Profiler::Profiler(QV4::ExecutionEngine *engine) : featuresEnabled(0), m_engine(
void Profiler::stopProfiling()
{
featuresEnabled = 0;
- reportData();
+ reportData(true);
+ m_sentLocations.clear();
}
bool operator<(const FunctionCall &call1, const FunctionCall &call2)
@@ -88,7 +89,7 @@ bool operator<(const FunctionCall &call1, const FunctionCall &call2)
(call1.m_end == call2.m_end && call1.m_function < call2.m_function)));
}
-void Profiler::reportData()
+void Profiler::reportData(bool trackLocations)
{
std::sort(m_data.begin(), m_data.end());
QVector<FunctionCallProperties> properties;
@@ -97,9 +98,15 @@ void Profiler::reportData()
foreach (const FunctionCall &call, m_data) {
properties.append(call.properties());
- FunctionLocation &location = locations[properties.constLast().id];
- if (!location.isValid())
- location = call.resolveLocation();
+ Function *function = call.function();
+ SentMarker &marker = m_sentLocations[reinterpret_cast<quintptr>(function)];
+ if (!trackLocations || !marker.isValid()) {
+ FunctionLocation &location = locations[properties.constLast().id];
+ if (!location.isValid())
+ location = call.resolveLocation();
+ if (trackLocations)
+ marker.setFunction(function);
+ }
}
emit dataReady(locations, properties, m_memory_data);
diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h
index bb128b7cf3..01fdf2951e 100644
--- a/src/qml/jsruntime/qv4profiling_p.h
+++ b/src/qml/jsruntime/qv4profiling_p.h
@@ -134,6 +134,11 @@ public:
return *this;
}
+ Function *function() const
+ {
+ return m_function;
+ }
+
FunctionLocation resolveLocation() const;
FunctionCallProperties properties() const;
@@ -165,6 +170,46 @@ class Q_QML_EXPORT Profiler : public QObject {
Q_OBJECT
Q_DISABLE_COPY(Profiler)
public:
+ struct SentMarker {
+ SentMarker() : m_function(nullptr) {}
+
+ SentMarker(const SentMarker &other) : m_function(other.m_function)
+ {
+ if (m_function)
+ m_function->compilationUnit->addref();
+ }
+
+ ~SentMarker()
+ {
+ if (m_function)
+ m_function->compilationUnit->release();
+ }
+
+ SentMarker &operator=(const SentMarker &other)
+ {
+ if (&other != this) {
+ if (m_function)
+ m_function->compilationUnit->release();
+ m_function = other.m_function;
+ m_function->compilationUnit->addref();
+ }
+ return *this;
+ }
+
+ void setFunction(Function *function)
+ {
+ Q_ASSERT(m_function == nullptr);
+ m_function = function;
+ m_function->compilationUnit->addref();
+ }
+
+ bool isValid() const
+ { return m_function != nullptr; }
+
+ private:
+ Function *m_function;
+ };
+
Profiler(QV4::ExecutionEngine *engine);
size_t trackAlloc(size_t size, MemoryType type)
@@ -186,7 +231,7 @@ public:
public slots:
void stopProfiling();
void startProfiling(quint64 features);
- void reportData();
+ void reportData(bool trackLocations);
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
signals:
@@ -199,6 +244,7 @@ private:
QElapsedTimer m_timer;
QVector<FunctionCall> m_data;
QVector<MemoryAllocationProperties> m_memory_data;
+ QHash<quintptr, SentMarker> m_sentLocations;
friend class FunctionCallProfiler;
};
@@ -237,6 +283,7 @@ Q_DECLARE_TYPEINFO(QV4::Profiling::MemoryAllocationProperties, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCallProperties, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCall, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionLocation, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QV4::Profiling::Profiler::SentMarker, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QV4::Profiling::FunctionLocationHash)
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index a6b24c4f16..9dba7f30d8 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -1017,7 +1017,9 @@ QV4::Heap::QmlContext *QQmlObjectCreator::currentQmlContext()
QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isContextObject)
{
- QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler);
+ const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
+ QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler, obj);
+
ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine));
bool isComponent = false;
@@ -1027,7 +1029,6 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
QQmlParserStatus *parserStatus = 0;
bool installPropertyCache = true;
- const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
if (obj->flags & QV4::CompiledData::Object::IsComponent) {
isComponent = true;
QQmlComponent *component = new QQmlComponent(engine, compiledData, index, parent);
diff --git a/src/qmldebug/qqmlprofilerclient.cpp b/src/qmldebug/qqmlprofilerclient.cpp
index 6f6b04ade9..29ccbb33b6 100644
--- a/src/qmldebug/qqmlprofilerclient.cpp
+++ b/src/qmldebug/qqmlprofilerclient.cpp
@@ -70,7 +70,7 @@ void QQmlProfilerClient::sendRecordingStatus(bool record, int engineId, quint32
Q_D(const QQmlProfilerClient);
QPacket stream(d->connection->currentDataStreamVersion());
- stream << record << engineId << d->features << flushInterval;
+ stream << record << engineId << d->features << flushInterval << true;
sendMessage(stream.data());
}
@@ -205,7 +205,7 @@ inline QQmlProfilerDefinitions::ProfileFeature featureFromRangeType(
void QQmlProfilerClient::messageReceived(const QByteArray &data)
{
- Q_D(const QQmlProfilerClient);
+ Q_D(QQmlProfilerClient);
QPacket stream(d->connection->currentDataStreamVersion(), data);
@@ -333,12 +333,25 @@ void QQmlProfilerClient::messageReceived(const QByteArray &data)
!(d->features & one << featureFromRangeType(rangeType)))
return;
+ qint64 typeId = 0;
if (messageType == QQmlProfilerDefinitions::RangeStart) {
rangeStart(rangeType, time);
+ if (!stream.atEnd()) {
+ stream >> typeId;
+ auto i = d->types.constFind(typeId);
+ if (i != d->types.constEnd()) {
+ rangeLocation(rangeType, time, i->location);
+ rangeData(rangeType, time, i->name);
+ }
+ }
} else if (messageType == QQmlProfilerDefinitions::RangeData) {
QString data;
stream >> data;
rangeData(rangeType, time, data);
+ if (!stream.atEnd()) {
+ stream >> typeId;
+ d->types[typeId].name = data;
+ }
} else if (messageType == QQmlProfilerDefinitions::RangeLocation) {
QQmlEventLocation location;
stream >> location.filename >> location.line;
@@ -347,6 +360,10 @@ void QQmlProfilerClient::messageReceived(const QByteArray &data)
stream >> location.column;
rangeLocation(rangeType, time, location);
+ if (!stream.atEnd()) {
+ stream >> typeId;
+ d->types[typeId].location = location;
+ }
} else if (messageType == QQmlProfilerDefinitions::RangeEnd) {
rangeEnd(rangeType, time);
} else {
diff --git a/src/qmldebug/qqmlprofilerclient_p_p.h b/src/qmldebug/qqmlprofilerclient_p_p.h
index 8238c97dd8..9c44113aa8 100644
--- a/src/qmldebug/qqmlprofilerclient_p_p.h
+++ b/src/qmldebug/qqmlprofilerclient_p_p.h
@@ -56,12 +56,20 @@
QT_BEGIN_NAMESPACE
+struct QQmlProfilerRangeType
+{
+ QQmlEventLocation location;
+ QString name;
+};
+
class QQmlProfilerClientPrivate : public QQmlDebugClientPrivate
{
Q_DECLARE_PUBLIC(QQmlProfilerClient)
public:
QQmlProfilerClientPrivate(QQmlDebugConnection *connection);
quint64 features;
+
+ QHash<qint64, QQmlProfilerRangeType> types;
};
QT_END_NAMESPACE
diff --git a/src/quick/util/qquickprofiler.cpp b/src/quick/util/qquickprofiler.cpp
index f8d090cc2c..659ffe1d84 100644
--- a/src/quick/util/qquickprofiler.cpp
+++ b/src/quick/util/qquickprofiler.cpp
@@ -110,8 +110,9 @@ void QQuickProfiler::stopProfilingImpl()
m_data.clear();
}
-void QQuickProfiler::reportDataImpl()
+void QQuickProfiler::reportDataImpl(bool trackLocations)
{
+ Q_UNUSED(trackLocations);
QMutexLocker lock(&m_dataMutex);
emit dataReady(m_data);
m_data.clear();
diff --git a/src/quick/util/qquickprofiler_p.h b/src/quick/util/qquickprofiler_p.h
index b58d4f47c1..f1af87f4e6 100644
--- a/src/quick/util/qquickprofiler_p.h
+++ b/src/quick/util/qquickprofiler_p.h
@@ -353,7 +353,7 @@ signals:
protected slots:
void startProfilingImpl(quint64 features);
void stopProfilingImpl();
- void reportDataImpl();
+ void reportDataImpl(bool trackLocations);
void setTimer(const QElapsedTimer &t);
};