aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2016-04-21 16:57:10 +0200
committerUlf Hermann <ulf.hermann@qt.io>2016-05-02 09:03:20 +0000
commita2e64a20777867726b51a9c9196dc1b8dd68f512 (patch)
tree3c0462e5b5db214c42f58e3bd6d5e48ae9cc2eed /src/plugins
parentd93daba909d0aeb8a32fe3b0e0a7145b60d77531 (diff)
V4 profiler: Don't duplicate function locations
Saving the name/file/line/column over and over for each function call is wasteful. We can instead key them by the pointer to the JS Function object. Also, make sure we don't accidentally detach the data when sending messages. Task-number: QTBUG-52937 Change-Id: I8a03e4003dc3239f88b49c56424df05cd8b9ef8a Reviewed-by: Anton Kudryavtsev <a.kudryavtsev@netris.ru> Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp46
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h4
2 files changed, 35 insertions, 15 deletions
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
index b50eef5545..68a71a5524 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
@@ -61,29 +61,35 @@ QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::Execut
connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
engine->profiler, SLOT(setTimer(QElapsedTimer)));
- connect(engine->profiler, SIGNAL(dataReady(QVector<QV4::Profiling::FunctionCallProperties>,
+ connect(engine->profiler, SIGNAL(dataReady(QV4::Profiling::FunctionLocationHash,
+ QVector<QV4::Profiling::FunctionCallProperties>,
QVector<QV4::Profiling::MemoryAllocationProperties>)),
- this, SLOT(receiveData(QVector<QV4::Profiling::FunctionCallProperties>,
+ this, SLOT(receiveData(QV4::Profiling::FunctionLocationHash,
+ QVector<QV4::Profiling::FunctionCallProperties>,
QVector<QV4::Profiling::MemoryAllocationProperties>)));
}
qint64 QV4ProfilerAdapter::appendMemoryEvents(qint64 until, QList<QByteArray> &messages,
QQmlDebugPacket &d)
{
- while (m_memoryData.length() > m_memoryPos && m_memoryData[m_memoryPos].timestamp <= until) {
- QV4::Profiling::MemoryAllocationProperties &props = m_memoryData[m_memoryPos];
+ // Make it const, so that we cannot accidentally detach it.
+ const QVector<QV4::Profiling::MemoryAllocationProperties> &memoryData = m_memoryData;
+
+ 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;
++m_memoryPos;
messages.append(d.squeezedData());
d.clear();
}
- return m_memoryData.length() == m_memoryPos ? -1 : m_memoryData[m_memoryPos].timestamp;
+ return memoryData.length() == m_memoryPos ? -1 : memoryData[m_memoryPos].timestamp;
}
qint64 QV4ProfilerAdapter::finalizeMessages(qint64 until, QList<QByteArray> &messages,
qint64 callNext, QQmlDebugPacket &d)
{
if (callNext == -1) {
+ m_functionLocations.clear();
m_functionCallData.clear();
m_functionCallPos = 0;
}
@@ -102,10 +108,15 @@ qint64 QV4ProfilerAdapter::finalizeMessages(qint64 until, QList<QByteArray> &mes
qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
{
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() &&
- (m_functionCallPos == m_functionCallData.length() ||
- m_stack.top() <= m_functionCallData[m_functionCallPos].start)) {
+ (m_functionCallPos == functionCallData.length() ||
+ m_stack.top() <= functionCallData[m_functionCallPos].start)) {
if (m_stack.top() > until || messages.length() > s_numMessagesPerBatch)
return finalizeMessages(until, messages, m_stack.top(), d);
@@ -114,39 +125,46 @@ qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &message
messages.append(d.squeezedData());
d.clear();
}
- while (m_functionCallPos != m_functionCallData.length() &&
- (m_stack.empty() || m_functionCallData[m_functionCallPos].start < m_stack.top())) {
+ while (m_functionCallPos != functionCallData.length() &&
+ (m_stack.empty() || functionCallData[m_functionCallPos].start < m_stack.top())) {
const QV4::Profiling::FunctionCallProperties &props =
- m_functionCallData[m_functionCallPos];
+ functionCallData[m_functionCallPos];
if (props.start > until || messages.length() > s_numMessagesPerBatch)
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 << props.file << props.line
- << props.column;
+ d << props.start << RangeLocation << Javascript << location->file << location->line
+ << location->column;
messages.push_back(d.squeezedData());
d.clear();
- d << props.start << RangeData << Javascript << props.name;
+ d << props.start << RangeData << Javascript << location->name;
messages.push_back(d.squeezedData());
d.clear();
m_stack.push(props.end);
++m_functionCallPos;
}
- if (m_stack.empty() && m_functionCallPos == m_functionCallData.length())
+ if (m_stack.empty() && m_functionCallPos == functionCallData.length())
return finalizeMessages(until, messages, -1, d);
}
}
void QV4ProfilerAdapter::receiveData(
+ const QV4::Profiling::FunctionLocationHash &locations,
const QVector<QV4::Profiling::FunctionCallProperties> &functionCallData,
const QVector<QV4::Profiling::MemoryAllocationProperties> &memoryData)
{
// In rare cases it could be that another flush or stop event is processed while data from
// the previous one is still pending. In that case we just append the data.
+ if (m_functionLocations.isEmpty())
+ m_functionLocations = locations;
+ else
+ m_functionLocations.unite(locations);
if (m_functionCallData.isEmpty())
m_functionCallData = functionCallData;
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
index f2985af98b..968825c346 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
@@ -74,7 +74,8 @@ signals:
void v4ProfilingEnabledWhileWaiting(quint64 v4Features);
public slots:
- void receiveData(const QVector<QV4::Profiling::FunctionCallProperties> &,
+ void receiveData(const QV4::Profiling::FunctionLocationHash &,
+ const QVector<QV4::Profiling::FunctionCallProperties> &,
const QVector<QV4::Profiling::MemoryAllocationProperties> &);
private slots:
@@ -82,6 +83,7 @@ private slots:
void forwardEnabledWhileWaiting(quint64 features);
private:
+ QV4::Profiling::FunctionLocationHash m_functionLocations;
QVector<QV4::Profiling::FunctionCallProperties> m_functionCallData;
QVector<QV4::Profiling::MemoryAllocationProperties> m_memoryData;
int m_functionCallPos;