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 <kai.koehne@nokia.com>
This commit is contained in:
Mikko Harju 2011-12-08 13:24:12 +02:00 committed by Qt by Nokia
parent d0dc58b8c3
commit 18ce33ecd9
3 changed files with 39 additions and 13 deletions

View File

@ -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<v8::String> 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);
}

View File

@ -84,7 +84,8 @@ public:
enum MessageType {
V8Entry,
V8Complete,
V8Snapshot,
V8SnapshotChunk,
V8SnapshotComplete,
V8MaximumMessage
};

View File

@ -88,9 +88,11 @@ public:
}
QList<QV8ProfilerData> traceMessages;
QList<QByteArray> 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"