From 18ce33ecd994666d42e438c4aa62302c72465458 Mon Sep 17 00:00:00 2001 From: Mikko Harju Date: Thu, 8 Dec 2011 13:24:12 +0200 Subject: [PATCH] QmlProfiler: stream snapshots to reduce memory footprint Taking a V8 heap snapshot with QV8ProfilerService created multiple copies of the snapshot data, causing overhead of several megabytes. This patch changes the snapshot protocol to stream the contents over the debugger connection. Change-Id: I90054210233d52dd02aa838201f9b024d578fcea Reviewed-by: Kai Koehne --- src/declarative/debugger/qv8profilerservice.cpp | 24 +++++++++++---------- src/declarative/debugger/qv8profilerservice_p.h | 3 ++- .../qv8profilerservice/tst_qv8profilerservice.cpp | 25 +++++++++++++++++++++- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/declarative/debugger/qv8profilerservice.cpp b/src/declarative/debugger/qv8profilerservice.cpp index cf6c04a..7cbd336 100644 --- a/src/declarative/debugger/qv8profilerservice.cpp +++ b/src/declarative/debugger/qv8profilerservice.cpp @@ -50,18 +50,20 @@ QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QV8ProfilerService, v8ProfilerInstance) -class ByteArrayOutputStream : public v8::OutputStream +class DebugServiceOutputStream : public v8::OutputStream { - QByteArray *_buffer; + QDeclarativeDebugService &_service; public: - ByteArrayOutputStream(QByteArray *buffer) + DebugServiceOutputStream(QDeclarativeDebugService &service) : v8::OutputStream(), - _buffer(buffer) {} + _service(service) {} void EndOfStream() {} - WriteResult WriteAsciiChunk(char *data, int size) + WriteResult WriteAsciiChunk(char *rawData, int size) { - QByteArray b(data, size); - _buffer->append(b); + QByteArray data; + QDataStream ds(&data, QIODevice::WriteOnly); + ds << QV8ProfilerService::V8SnapshotChunk << QByteArray(rawData, size); + _service.sendMessage(data); return kContinue; } }; @@ -223,14 +225,14 @@ void QV8ProfilerServicePrivate::takeSnapshot(v8::HeapSnapshot::Type snapshotType v8::HandleScope scope; v8::Local title = v8::String::New(""); - QByteArray jsonSnapshot; - ByteArrayOutputStream bos(&jsonSnapshot); + DebugServiceOutputStream outputStream(*q); const v8::HeapSnapshot *snapshot = v8::HeapProfiler::TakeSnapshot(title, snapshotType); - snapshot->Serialize(&bos, v8::HeapSnapshot::kJSON); + snapshot->Serialize(&outputStream, v8::HeapSnapshot::kJSON); + //indicate completion QByteArray data; QDataStream ds(&data, QIODevice::WriteOnly); - ds << (int)QV8ProfilerService::V8Snapshot << jsonSnapshot; + ds << (int)QV8ProfilerService::V8SnapshotComplete; q->sendMessage(data); } diff --git a/src/declarative/debugger/qv8profilerservice_p.h b/src/declarative/debugger/qv8profilerservice_p.h index c2b63bd..7868659 100644 --- a/src/declarative/debugger/qv8profilerservice_p.h +++ b/src/declarative/debugger/qv8profilerservice_p.h @@ -84,7 +84,8 @@ public: enum MessageType { V8Entry, V8Complete, - V8Snapshot, + V8SnapshotChunk, + V8SnapshotComplete, V8MaximumMessage }; diff --git a/tests/auto/declarative/debugger/qv8profilerservice/tst_qv8profilerservice.cpp b/tests/auto/declarative/debugger/qv8profilerservice/tst_qv8profilerservice.cpp index 0739c74..46c587d 100644 --- a/tests/auto/declarative/debugger/qv8profilerservice/tst_qv8profilerservice.cpp +++ b/tests/auto/declarative/debugger/qv8profilerservice/tst_qv8profilerservice.cpp @@ -88,9 +88,11 @@ public: } QList traceMessages; + QList snapshotMessages; signals: void complete(); + void snapshot(); protected: void messageReceived(const QByteArray &message); @@ -121,6 +123,7 @@ private slots: void blockingConnectWithTraceEnabled(); void blockingConnectWithTraceDisabled(); void nonBlockingConnect(); + void snapshot(); }; void QV8ProfilerClient::messageReceived(const QByteArray &message) @@ -144,7 +147,14 @@ void QV8ProfilerClient::messageReceived(const QByteArray &message) case QV8ProfilerService::V8Complete: emit complete(); break; - case QV8ProfilerService::V8Snapshot: + case QV8ProfilerService::V8SnapshotChunk: { + QByteArray json; + stream >> json; + snapshotMessages.append(json); + break; + } + case QV8ProfilerService::V8SnapshotComplete: + emit snapshot(); break; default: QString failMessage = QString("Unknown message type: %1").arg(messageType); @@ -230,6 +240,19 @@ void tst_QV8ProfilerService::nonBlockingConnect() } } +void tst_QV8ProfilerService::snapshot() +{ + connect(false); + QTRY_COMPARE(m_client->status(), QDeclarativeDebugClient::Enabled); + + m_client->takeSnapshot(); + if (!QDeclarativeDebugTest::waitForSignal(m_client, SIGNAL(snapshot()))) { + QString failMsg + = QString("No snapshot received in time. App output: %1\n\n").arg(m_process->output()); + QFAIL(qPrintable(failMsg)); + } +} + QTEST_MAIN(tst_QV8ProfilerService) #include "tst_qv8profilerservice.moc" -- 2.7.4