forked from qt-creator/qt-creator
QmlProfiler: Use a temporary file to store the master event list
As we only ever iterate the master event list in a linear fashion, we can use a temporary file to store it. This should allow for larger traces to be handled without running out of memory. Change-Id: I0d2aea6f998458fe5f426f6fef0f6937e915ae68 Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
This commit is contained in:
@@ -34,6 +34,7 @@
|
|||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QStack>
|
#include <QStack>
|
||||||
|
#include <QTemporaryFile>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace QmlProfiler {
|
namespace QmlProfiler {
|
||||||
@@ -46,7 +47,6 @@ public:
|
|||||||
int resolveStackTop();
|
int resolveStackTop();
|
||||||
|
|
||||||
QVector<QmlEventType> eventTypes;
|
QVector<QmlEventType> eventTypes;
|
||||||
QVector<QmlEvent> eventList;
|
|
||||||
QHash<QmlEventType, int> eventTypeIds;
|
QHash<QmlEventType, int> eventTypeIds;
|
||||||
|
|
||||||
QStack<QmlTypedEvent> rangesInProgress;
|
QStack<QmlTypedEvent> rangesInProgress;
|
||||||
@@ -54,6 +54,9 @@ public:
|
|||||||
QmlProfilerModelManager *modelManager;
|
QmlProfilerModelManager *modelManager;
|
||||||
int modelId;
|
int modelId;
|
||||||
Internal::QmlProfilerDetailsRewriter *detailsRewriter;
|
Internal::QmlProfilerDetailsRewriter *detailsRewriter;
|
||||||
|
|
||||||
|
QTemporaryFile file;
|
||||||
|
QDataStream eventStream;
|
||||||
};
|
};
|
||||||
|
|
||||||
QString getDisplayName(const QmlEventType &event)
|
QString getDisplayName(const QmlEventType &event)
|
||||||
@@ -117,6 +120,8 @@ QmlProfilerDataModel::QmlProfilerDataModel(Utils::FileInProjectFinder *fileFinde
|
|||||||
this, &QmlProfilerDataModel::detailsChanged);
|
this, &QmlProfilerDataModel::detailsChanged);
|
||||||
connect(d->detailsRewriter, &QmlProfilerDetailsRewriter::eventDetailsChanged,
|
connect(d->detailsRewriter, &QmlProfilerDetailsRewriter::eventDetailsChanged,
|
||||||
this, &QmlProfilerDataModel::allTypesLoaded);
|
this, &QmlProfilerDataModel::allTypesLoaded);
|
||||||
|
d->file.open();
|
||||||
|
d->eventStream.setDevice(&d->file);
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlProfilerDataModel::~QmlProfilerDataModel()
|
QmlProfilerDataModel::~QmlProfilerDataModel()
|
||||||
@@ -138,25 +143,22 @@ void QmlProfilerDataModel::setData(qint64 traceStart, qint64 traceEnd,
|
|||||||
{
|
{
|
||||||
Q_D(QmlProfilerDataModel);
|
Q_D(QmlProfilerDataModel);
|
||||||
d->modelManager->traceTime()->setTime(traceStart, traceEnd);
|
d->modelManager->traceTime()->setTime(traceStart, traceEnd);
|
||||||
d->eventList = events;
|
|
||||||
d->eventTypes = types;
|
d->eventTypes = types;
|
||||||
for (int id = 0; id < types.count(); ++id)
|
for (int id = 0; id < types.count(); ++id)
|
||||||
d->eventTypeIds[types[id]] = id;
|
d->eventTypeIds[types[id]] = id;
|
||||||
|
|
||||||
foreach (const QmlEvent &event, d->eventList)
|
foreach (const QmlEvent &event, events) {
|
||||||
d->modelManager->dispatch(event, d->eventTypes[event.typeIndex()]);
|
d->modelManager->dispatch(event, d->eventTypes[event.typeIndex()]);
|
||||||
|
d->eventStream << event;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QmlProfilerDataModel::count() const
|
|
||||||
{
|
|
||||||
Q_D(const QmlProfilerDataModel);
|
|
||||||
return d->eventList.count();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerDataModel::clear()
|
void QmlProfilerDataModel::clear()
|
||||||
{
|
{
|
||||||
Q_D(QmlProfilerDataModel);
|
Q_D(QmlProfilerDataModel);
|
||||||
d->eventList.clear();
|
d->file.remove();
|
||||||
|
d->file.open();
|
||||||
|
d->eventStream.setDevice(&d->file);
|
||||||
d->eventTypes.clear();
|
d->eventTypes.clear();
|
||||||
d->eventTypeIds.clear();
|
d->eventTypeIds.clear();
|
||||||
d->rangesInProgress.clear();
|
d->rangesInProgress.clear();
|
||||||
@@ -166,7 +168,7 @@ void QmlProfilerDataModel::clear()
|
|||||||
bool QmlProfilerDataModel::isEmpty() const
|
bool QmlProfilerDataModel::isEmpty() const
|
||||||
{
|
{
|
||||||
Q_D(const QmlProfilerDataModel);
|
Q_D(const QmlProfilerDataModel);
|
||||||
return d->eventList.isEmpty();
|
return d->file.pos() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static uint qHash(const QmlEventType &type)
|
inline static uint qHash(const QmlEventType &type)
|
||||||
@@ -234,8 +236,8 @@ int QmlProfilerDataModel::QmlProfilerDataModelPrivate::resolveStackTop()
|
|||||||
|
|
||||||
typeIndex = resolveType(typedEvent.type);
|
typeIndex = resolveType(typedEvent.type);
|
||||||
typedEvent.event.setTypeIndex(typeIndex);
|
typedEvent.event.setTypeIndex(typeIndex);
|
||||||
eventList.append(typedEvent.event);
|
eventStream << typedEvent.event;
|
||||||
modelManager->dispatch(eventList.last(), eventTypes[typeIndex]);
|
modelManager->dispatch(typedEvent.event, eventTypes[typeIndex]);
|
||||||
return typeIndex;
|
return typeIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,9 +258,9 @@ void QmlProfilerDataModel::addEvent(const QmlEvent &event, const QmlEventType &t
|
|||||||
case RangeEnd: {
|
case RangeEnd: {
|
||||||
int typeIndex = d->resolveStackTop();
|
int typeIndex = d->resolveStackTop();
|
||||||
QTC_ASSERT(typeIndex != -1, break);
|
QTC_ASSERT(typeIndex != -1, break);
|
||||||
d->eventList.append(event);
|
QmlEvent appended = event;
|
||||||
QmlEvent &appended = d->eventList.last();
|
|
||||||
appended.setTypeIndex(typeIndex);
|
appended.setTypeIndex(typeIndex);
|
||||||
|
d->eventStream << appended;
|
||||||
d->modelManager->dispatch(appended, d->eventTypes[typeIndex]);
|
d->modelManager->dispatch(appended, d->eventTypes[typeIndex]);
|
||||||
d->rangesInProgress.pop();
|
d->rangesInProgress.pop();
|
||||||
break;
|
break;
|
||||||
@@ -270,10 +272,10 @@ void QmlProfilerDataModel::addEvent(const QmlEvent &event, const QmlEventType &t
|
|||||||
d->rangesInProgress.top().type.location = type.location;
|
d->rangesInProgress.top().type.location = type.location;
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
d->eventList.append(event);
|
QmlEvent appended = event;
|
||||||
QmlEvent &appended = d->eventList.last();
|
|
||||||
int typeIndex = d->resolveType(type);
|
int typeIndex = d->resolveType(type);
|
||||||
appended.setTypeIndex(typeIndex);
|
appended.setTypeIndex(typeIndex);
|
||||||
|
d->eventStream << appended;
|
||||||
d->modelManager->dispatch(appended, d->eventTypes[typeIndex]);
|
d->modelManager->dispatch(appended, d->eventTypes[typeIndex]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -285,7 +287,15 @@ void QmlProfilerDataModel::replayEvents(qint64 rangeStart, qint64 rangeEnd,
|
|||||||
{
|
{
|
||||||
Q_D(const QmlProfilerDataModel);
|
Q_D(const QmlProfilerDataModel);
|
||||||
QStack<QmlEvent> stack;
|
QStack<QmlEvent> stack;
|
||||||
foreach (const QmlEvent &event, d->eventList) {
|
QmlEvent event;
|
||||||
|
QFile file(d->file.fileName());
|
||||||
|
file.open(QIODevice::ReadOnly);
|
||||||
|
QDataStream stream(&file);
|
||||||
|
while (!stream.atEnd()) {
|
||||||
|
stream >> event;
|
||||||
|
if (stream.status() == QDataStream::ReadPastEnd)
|
||||||
|
break;
|
||||||
|
|
||||||
const QmlEventType &type = d->eventTypes[event.typeIndex()];
|
const QmlEventType &type = d->eventTypes[event.typeIndex()];
|
||||||
if (rangeStart != -1 && rangeEnd != -1) {
|
if (rangeStart != -1 && rangeEnd != -1) {
|
||||||
if (event.timestamp() < rangeStart) {
|
if (event.timestamp() < rangeStart) {
|
||||||
@@ -324,18 +334,10 @@ void QmlProfilerDataModel::replayEvents(qint64 rangeStart, qint64 rangeEnd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 QmlProfilerDataModel::lastTimeMark() const
|
|
||||||
{
|
|
||||||
Q_D(const QmlProfilerDataModel);
|
|
||||||
if (d->eventList.isEmpty())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return d->eventList.last().timestamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlProfilerDataModel::finalize()
|
void QmlProfilerDataModel::finalize()
|
||||||
{
|
{
|
||||||
Q_D(QmlProfilerDataModel);
|
Q_D(QmlProfilerDataModel);
|
||||||
|
d->file.flush();
|
||||||
d->detailsRewriter->reloadDocuments();
|
d->detailsRewriter->reloadDocuments();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,14 +49,12 @@ public:
|
|||||||
void setData(qint64 traceStart, qint64 traceEnd, const QVector<QmlEventType> &types,
|
void setData(qint64 traceStart, qint64 traceEnd, const QVector<QmlEventType> &types,
|
||||||
const QVector<QmlEvent> &events);
|
const QVector<QmlEvent> &events);
|
||||||
|
|
||||||
int count() const;
|
|
||||||
void clear();
|
void clear();
|
||||||
bool isEmpty() const;
|
bool isEmpty() const;
|
||||||
void addEvent(const QmlEvent &event, const QmlEventType &type);
|
void addEvent(const QmlEvent &event, const QmlEventType &type);
|
||||||
void replayEvents(qint64 startTime, qint64 endTime,
|
void replayEvents(qint64 startTime, qint64 endTime,
|
||||||
QmlProfilerModelManager::EventLoader loader) const;
|
QmlProfilerModelManager::EventLoader loader) const;
|
||||||
void finalize();
|
void finalize();
|
||||||
qint64 lastTimeMark() const;
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void allTypesLoaded();
|
void allTypesLoaded();
|
||||||
|
|||||||
@@ -343,7 +343,7 @@ void QmlProfilerModelManager::load(const QString &filename)
|
|||||||
reader->eventTypes(), reader->events());
|
reader->eventTypes(), reader->events());
|
||||||
d->notesModel->setNotes(reader->notes());
|
d->notesModel->setNotes(reader->notes());
|
||||||
setRecordedFeatures(reader->loadedFeatures());
|
setRecordedFeatures(reader->loadedFeatures());
|
||||||
d->traceTime->increaseEndTime(d->model->lastTimeMark());
|
d->traceTime->increaseEndTime(reader->events().last().timestamp());
|
||||||
delete reader;
|
delete reader;
|
||||||
acquiringDone();
|
acquiringDone();
|
||||||
}, Qt::QueuedConnection);
|
}, Qt::QueuedConnection);
|
||||||
|
|||||||
@@ -522,8 +522,7 @@ void QmlProfilerFileWriter::setFuture(QFutureInterface<void> *future)
|
|||||||
void QmlProfilerFileWriter::save(QIODevice *device)
|
void QmlProfilerFileWriter::save(QIODevice *device)
|
||||||
{
|
{
|
||||||
if (m_future) {
|
if (m_future) {
|
||||||
m_future->setProgressRange(
|
m_future->setProgressRange(0, qMax(m_model->eventTypes().size() + m_notes.size(), 1));
|
||||||
0, qMax(m_model->eventTypes().size() + m_model->count() + m_notes.size(), 1));
|
|
||||||
m_future->setProgressValue(0);
|
m_future->setProgressValue(0);
|
||||||
m_newProgressValue = 0;
|
m_newProgressValue = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user