forked from qt-creator/qt-creator
QmlProfiler: Add a QmlTypedEvent and extend QmlEvent
The QmlTypedEvent is mainly useful to read a generic QmlEvent and QmlEventType from a QPacket. QmlEventType has a stream operator to do exactly that. QmlEvent also gets further options to store 32-bit data in addition to 64- and 8-bit data. Also, with the more generic storage layout we can reduce the memory consumption of range events by 50%. This comes at the cost of additional memory allocations for non-range events, but as non-range events are significantly less frequent than range events, this is a good tradeoff. Finally the new storage layout lends itself to efficient serialization, which will help when developing new storage and transfer formats for QML traces. Change-Id: I420de68b0142f23c8fb2ca8b329d7ffe69c83fe0 Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
This commit is contained in:
@@ -113,7 +113,7 @@ void DebugMessagesModel::loadData()
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
m_data.insert(insert(event.timestamp(), 0, type.detailType),
|
m_data.insert(insert(event.timestamp(), 0, type.detailType),
|
||||||
MessageData(event.stringData(), event.typeIndex()));
|
MessageData(event.string(), event.typeIndex()));
|
||||||
if (type.detailType > m_maximumMsgType)
|
if (type.detailType > m_maximumMsgType)
|
||||||
m_maximumMsgType = event.typeIndex();
|
m_maximumMsgType = event.typeIndex();
|
||||||
updateProgress(count(), simpleModel->events().count());
|
updateProgress(count(), simpleModel->events().count());
|
||||||
|
@@ -153,8 +153,8 @@ void InputEventsModel::loadData()
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
m_data.insert(insert(event.timestamp(), 0, type.detailType),
|
m_data.insert(insert(event.timestamp(), 0, type.detailType),
|
||||||
InputEvent(static_cast<InputEventType>(event.numericData(0)),
|
InputEvent(static_cast<InputEventType>(event.number<qint32>(0)),
|
||||||
event.numericData(1), event.numericData(2)));
|
event.number<qint32>(1), event.number<qint32>(2)));
|
||||||
|
|
||||||
if (type.detailType == Mouse) {
|
if (type.detailType == Mouse) {
|
||||||
if (m_mouseTypeId == -1)
|
if (m_mouseTypeId == -1)
|
||||||
|
@@ -177,12 +177,12 @@ void MemoryUsageModel::loadData()
|
|||||||
type.detailType == selectionId(currentUsageIndex) &&
|
type.detailType == selectionId(currentUsageIndex) &&
|
||||||
m_data[currentUsageIndex].originTypeIndex == rangeStack.top().originTypeIndex &&
|
m_data[currentUsageIndex].originTypeIndex == rangeStack.top().originTypeIndex &&
|
||||||
rangeStack.top().startTime < startTime(currentUsageIndex)) {
|
rangeStack.top().startTime < startTime(currentUsageIndex)) {
|
||||||
m_data[currentUsageIndex].update(event.numericData(0));
|
m_data[currentUsageIndex].update(event.number<qint64>(0));
|
||||||
currentUsage = m_data[currentUsageIndex].size;
|
currentUsage = m_data[currentUsageIndex].size;
|
||||||
} else {
|
} else {
|
||||||
MemoryAllocationItem allocation(event.typeIndex(), currentUsage,
|
MemoryAllocationItem allocation(event.typeIndex(), currentUsage,
|
||||||
rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex);
|
rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex);
|
||||||
allocation.update(event.numericData(0));
|
allocation.update(event.number<qint64>(0));
|
||||||
currentUsage = allocation.size;
|
currentUsage = allocation.size;
|
||||||
|
|
||||||
if (currentUsageIndex != -1) {
|
if (currentUsageIndex != -1) {
|
||||||
@@ -200,12 +200,12 @@ void MemoryUsageModel::loadData()
|
|||||||
m_data[currentJSHeapIndex].originTypeIndex ==
|
m_data[currentJSHeapIndex].originTypeIndex ==
|
||||||
rangeStack.top().originTypeIndex &&
|
rangeStack.top().originTypeIndex &&
|
||||||
rangeStack.top().startTime < startTime(currentJSHeapIndex)) {
|
rangeStack.top().startTime < startTime(currentJSHeapIndex)) {
|
||||||
m_data[currentJSHeapIndex].update(event.numericData(0));
|
m_data[currentJSHeapIndex].update(event.number<qint64>(0));
|
||||||
currentSize = m_data[currentJSHeapIndex].size;
|
currentSize = m_data[currentJSHeapIndex].size;
|
||||||
} else {
|
} else {
|
||||||
MemoryAllocationItem allocation(event.typeIndex(), currentSize,
|
MemoryAllocationItem allocation(event.typeIndex(), currentSize,
|
||||||
rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex);
|
rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex);
|
||||||
allocation.update(event.numericData(0));
|
allocation.update(event.number<qint64>(0));
|
||||||
currentSize = allocation.size;
|
currentSize = allocation.size;
|
||||||
|
|
||||||
if (currentSize > m_maxSize)
|
if (currentSize > m_maxSize)
|
||||||
|
@@ -211,15 +211,15 @@ void PixmapCacheModel::loadData()
|
|||||||
// We can't have cached it before we knew the size
|
// We can't have cached it before we knew the size
|
||||||
Q_ASSERT(i->cacheState != Cached);
|
Q_ASSERT(i->cacheState != Cached);
|
||||||
|
|
||||||
i->size.setWidth(event.numericData(0));
|
i->size.setWidth(event.number<qint32>(0));
|
||||||
i->size.setHeight(event.numericData(1));
|
i->size.setHeight(event.number<qint32>(1));
|
||||||
newEvent.sizeIndex = i - pixmap.sizes.begin();
|
newEvent.sizeIndex = i - pixmap.sizes.begin();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newEvent.sizeIndex == -1) {
|
if (newEvent.sizeIndex == -1) {
|
||||||
newEvent.sizeIndex = pixmap.sizes.length();
|
newEvent.sizeIndex = pixmap.sizes.length();
|
||||||
pixmap.sizes << PixmapState(event.numericData(0), event.numericData(1));
|
pixmap.sizes << PixmapState(event.number<qint32>(0), event.number<qint32>(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
PixmapState &state = pixmap.sizes[newEvent.sizeIndex];
|
PixmapState &state = pixmap.sizes[newEvent.sizeIndex];
|
||||||
@@ -234,8 +234,8 @@ void PixmapCacheModel::loadData()
|
|||||||
case PixmapCacheCountChanged: {// Cache Size Changed Event
|
case PixmapCacheCountChanged: {// Cache Size Changed Event
|
||||||
pixmapStartTime = event.timestamp() + 1; // delay 1 ns for proper sorting
|
pixmapStartTime = event.timestamp() + 1; // delay 1 ns for proper sorting
|
||||||
|
|
||||||
bool uncache = cumulatedCount > event.numericData(2);
|
bool uncache = cumulatedCount > event.number<qint32>(2);
|
||||||
cumulatedCount = event.numericData(2);
|
cumulatedCount = event.number<qint32>(2);
|
||||||
qint64 pixSize = 0;
|
qint64 pixSize = 0;
|
||||||
|
|
||||||
// First try to find a preferred pixmap, which either is Corrupt and will be uncached
|
// First try to find a preferred pixmap, which either is Corrupt and will be uncached
|
||||||
|
@@ -24,33 +24,45 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "qmlprofilereventtypes.h"
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QVarLengthArray>
|
||||||
|
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace QmlProfiler {
|
namespace QmlProfiler {
|
||||||
|
|
||||||
struct QmlEvent {
|
struct QmlEvent {
|
||||||
QmlEvent(qint64 timestamp = -1, qint64 duration = -1, int typeIndex = -1,
|
QmlEvent() : m_timestamp(-1), m_duration(0), m_typeIndex(-1), m_dataType(Inline8Bit),
|
||||||
qint64 num0 = 0, qint64 num1 = 0, qint64 num2 = 0, qint64 num3 = 0,
|
m_dataLength(0) {}
|
||||||
qint64 num4 = 0) :
|
|
||||||
m_timestamp(timestamp), m_duration(duration), m_dataType(NumericData),
|
template<typename Number>
|
||||||
m_typeIndex(typeIndex)
|
QmlEvent(qint64 timestamp, qint64 duration, int typeIndex, std::initializer_list<Number> list)
|
||||||
|
: m_timestamp(timestamp), m_duration(duration), m_typeIndex(typeIndex)
|
||||||
{
|
{
|
||||||
m_numericData[0] = num0;
|
assignNumbers<std::initializer_list<Number>, Number>(list);
|
||||||
m_numericData[1] = num1;
|
|
||||||
m_numericData[2] = num2;
|
|
||||||
m_numericData[3] = num3;
|
|
||||||
m_numericData[4] = num4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlEvent(qint64 timestamp, qint64 duration, int typeIndex, const QString &data)
|
QmlEvent(qint64 timestamp, qint64 duration, int typeIndex, const QString &data)
|
||||||
: m_timestamp(timestamp), m_duration(duration), m_typeIndex(typeIndex)
|
: m_timestamp(timestamp), m_duration(duration), m_typeIndex(typeIndex)
|
||||||
{
|
{
|
||||||
assignStringData(data);
|
assignNumbers<QByteArray, qint8>(data.toUtf8());
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlEvent(const QmlEvent &other) :
|
template<typename Number>
|
||||||
m_timestamp(other.m_timestamp), m_duration(other.m_duration),
|
QmlEvent(qint64 timestamp, qint64 duration, int typeIndex, const QVector<Number> &data)
|
||||||
m_dataType(other.m_dataType), m_typeIndex(other.m_typeIndex)
|
: m_timestamp(timestamp), m_duration(duration), m_typeIndex(typeIndex)
|
||||||
|
{
|
||||||
|
assignNumbers<QVector<Number>, Number>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlEvent(const QmlEvent &other)
|
||||||
|
: m_timestamp(other.m_timestamp), m_duration(other.m_duration),
|
||||||
|
m_typeIndex(other.m_typeIndex), m_dataType(other.m_dataType),
|
||||||
|
m_dataLength(other.m_dataLength)
|
||||||
{
|
{
|
||||||
assignData(other);
|
assignData(other);
|
||||||
}
|
}
|
||||||
@@ -58,13 +70,12 @@ struct QmlEvent {
|
|||||||
QmlEvent &operator=(const QmlEvent &other)
|
QmlEvent &operator=(const QmlEvent &other)
|
||||||
{
|
{
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
if (m_dataType == StringData)
|
clearPointer();
|
||||||
delete m_stringData;
|
|
||||||
|
|
||||||
m_timestamp = other.m_timestamp;
|
m_timestamp = other.m_timestamp;
|
||||||
m_duration = other.m_duration;
|
m_duration = other.m_duration;
|
||||||
m_typeIndex = other.m_typeIndex;
|
m_typeIndex = other.m_typeIndex;
|
||||||
m_dataType = other.m_dataType;
|
m_dataType = other.m_dataType;
|
||||||
|
m_dataLength = other.m_dataLength;
|
||||||
assignData(other);
|
assignData(other);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
@@ -72,8 +83,7 @@ struct QmlEvent {
|
|||||||
|
|
||||||
~QmlEvent()
|
~QmlEvent()
|
||||||
{
|
{
|
||||||
if (m_dataType == StringData)
|
clearPointer();
|
||||||
delete m_stringData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 timestamp() const { return m_timestamp; }
|
qint64 timestamp() const { return m_timestamp; }
|
||||||
@@ -85,31 +95,102 @@ struct QmlEvent {
|
|||||||
int typeIndex() const { return m_typeIndex; }
|
int typeIndex() const { return m_typeIndex; }
|
||||||
void setTypeIndex(int typeIndex) { m_typeIndex = typeIndex; }
|
void setTypeIndex(int typeIndex) { m_typeIndex = typeIndex; }
|
||||||
|
|
||||||
qint64 numericData(int i) const { return m_dataType == NumericData ? m_numericData[i] : 0; }
|
template<typename Number>
|
||||||
void setNumericData(int i, qint64 data)
|
Number number(int i) const
|
||||||
{
|
|
||||||
if (m_dataType == StringData)
|
|
||||||
delete m_stringData;
|
|
||||||
|
|
||||||
m_dataType = NumericData;
|
|
||||||
m_numericData[i] = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString stringData() const
|
|
||||||
{
|
{
|
||||||
|
// Trailing zeroes can be omitted, for example for SceneGraph events
|
||||||
|
if (i >= m_dataLength)
|
||||||
|
return 0;
|
||||||
switch (m_dataType) {
|
switch (m_dataType) {
|
||||||
case NumericData: return QString();
|
case Inline8Bit:
|
||||||
case StringData: return *m_stringData;
|
return m_data.internal8bit[i];
|
||||||
default: return QString::fromUtf8(m_characterData, m_characterDataLength);
|
case Inline16Bit:
|
||||||
|
return m_data.internal16bit[i];
|
||||||
|
case Inline32Bit:
|
||||||
|
return m_data.internal32bit[i];
|
||||||
|
case Inline64Bit:
|
||||||
|
return m_data.internal64bit[i];
|
||||||
|
case External8Bit:
|
||||||
|
return static_cast<const qint8 *>(m_data.external)[i];
|
||||||
|
case External16Bit:
|
||||||
|
return static_cast<const qint16 *>(m_data.external)[i];
|
||||||
|
case External32Bit:
|
||||||
|
return static_cast<const qint32 *>(m_data.external)[i];
|
||||||
|
case External64Bit:
|
||||||
|
return static_cast<const qint64 *>(m_data.external)[i];
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setStringData(const QString &data)
|
template<typename Number>
|
||||||
|
void setNumber(int i, Number number)
|
||||||
{
|
{
|
||||||
if (m_dataType == StringData)
|
QVarLengthArray<Number> nums = numbers<QVarLengthArray<Number>, Number>();
|
||||||
delete m_stringData;
|
int prevSize = nums.size();
|
||||||
|
if (i >= prevSize) {
|
||||||
|
nums.resize(i + 1);
|
||||||
|
// Fill with zeroes. We don't want to accidentally prevent squeezing.
|
||||||
|
while (prevSize < i)
|
||||||
|
nums[prevSize++] = 0;
|
||||||
|
}
|
||||||
|
nums[i] = number;
|
||||||
|
setNumbers<QVarLengthArray<Number>, Number>(nums);
|
||||||
|
}
|
||||||
|
|
||||||
assignStringData(data);
|
template<typename Container, typename Number>
|
||||||
|
void setNumbers(const Container &numbers)
|
||||||
|
{
|
||||||
|
clearPointer();
|
||||||
|
assignNumbers<Container, Number>(numbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Number>
|
||||||
|
void setNumbers(std::initializer_list<Number> numbers)
|
||||||
|
{
|
||||||
|
setNumbers<std::initializer_list<Number>, Number>(numbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Container, typename Number>
|
||||||
|
Container numbers() const
|
||||||
|
{
|
||||||
|
Container container;
|
||||||
|
for (int i = 0; i < m_dataLength; ++i)
|
||||||
|
container.append(number<Number>(i));
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString string() const
|
||||||
|
{
|
||||||
|
switch (m_dataType) {
|
||||||
|
case External8Bit:
|
||||||
|
return QString::fromUtf8(static_cast<const char *>(m_data.external));
|
||||||
|
case Inline8Bit:
|
||||||
|
return QString::fromUtf8(m_data.internalChar);
|
||||||
|
default:
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setString(const QString &data)
|
||||||
|
{
|
||||||
|
clearPointer();
|
||||||
|
assignNumbers<QByteArray, char>(data.toUtf8());
|
||||||
|
}
|
||||||
|
|
||||||
|
Message rangeStage() const
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_dataType == Inline8Bit);
|
||||||
|
return static_cast<Message>(m_data.internal8bit[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRangeStage(Message stage)
|
||||||
|
{
|
||||||
|
clearPointer();
|
||||||
|
m_dataType = Inline8Bit;
|
||||||
|
m_dataLength = 1;
|
||||||
|
m_data.internal8bit[0] = stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isValid() const
|
bool isValid() const
|
||||||
@@ -118,50 +199,96 @@ struct QmlEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum Type: quint16 {
|
||||||
static const quint8 StringData = 254;
|
External = 1,
|
||||||
static const quint8 NumericData = 255;
|
Inline8Bit = 8,
|
||||||
|
External8Bit = Inline8Bit | External,
|
||||||
|
Inline16Bit = 16,
|
||||||
|
External16Bit = Inline16Bit | External,
|
||||||
|
Inline32Bit = 32,
|
||||||
|
External32Bit = Inline32Bit | External,
|
||||||
|
Inline64Bit = 64,
|
||||||
|
External64Bit = Inline64Bit | External
|
||||||
|
};
|
||||||
|
|
||||||
qint64 m_timestamp;
|
qint64 m_timestamp;
|
||||||
qint64 m_duration;
|
qint64 m_duration;
|
||||||
union {
|
|
||||||
qint64 m_numericData[5];
|
|
||||||
QString *m_stringData;
|
|
||||||
char m_characterData[5 * sizeof(qint64) + 3];
|
|
||||||
};
|
|
||||||
|
|
||||||
union {
|
union {
|
||||||
quint8 m_dataType;
|
void *external;
|
||||||
quint8 m_characterDataLength;
|
char internalChar [sizeof(external)];
|
||||||
};
|
qint8 internal8bit [sizeof(external)];
|
||||||
|
qint16 internal16bit[sizeof(external) / 2];
|
||||||
|
qint32 internal32bit[sizeof(external) / 4];
|
||||||
|
qint64 internal64bit[sizeof(external) / 8];
|
||||||
|
} m_data;
|
||||||
|
|
||||||
qint32 m_typeIndex;
|
qint32 m_typeIndex;
|
||||||
|
Type m_dataType;
|
||||||
|
quint16 m_dataLength;
|
||||||
|
|
||||||
void assignData(const QmlEvent &other)
|
void assignData(const QmlEvent &other)
|
||||||
{
|
{
|
||||||
switch (m_dataType) {
|
if (m_dataType & External) {
|
||||||
case StringData:
|
int length = m_dataLength * (other.m_dataType / 8);
|
||||||
m_stringData = new QString(*other.m_stringData);
|
m_data.external = malloc(length);
|
||||||
break;
|
memcpy(m_data.external, other.m_data.external, length);
|
||||||
case NumericData:
|
} else {
|
||||||
for (int i = 0; i < 5; ++i)
|
memcpy(&m_data, &other.m_data, sizeof(m_data));
|
||||||
m_numericData[i] = other.m_numericData[i];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
memcpy(m_characterData, other.m_characterData, m_characterDataLength);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void assignStringData(const QString &data)
|
template<typename Big, typename Small>
|
||||||
|
bool squeezable(Big source)
|
||||||
{
|
{
|
||||||
QByteArray cdata = data.toUtf8();
|
return static_cast<Small>(source) == source;
|
||||||
if (cdata.length() <= (int)sizeof(m_characterData)) {
|
}
|
||||||
m_characterDataLength = cdata.length();
|
|
||||||
memcpy(m_characterData, cdata.constData(), m_characterDataLength);
|
template<typename Container, typename Number>
|
||||||
} else {
|
typename std::enable_if<(sizeof(Number) > 1), bool>::type
|
||||||
m_dataType = StringData;
|
squeeze(const Container &numbers)
|
||||||
m_stringData = new QString(data);
|
{
|
||||||
|
typedef typename QIntegerForSize<sizeof(Number) / 2>::Signed Small;
|
||||||
|
foreach (Number item, numbers) {
|
||||||
|
if (!squeezable<Number, Small>(item))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
assignNumbers<Container, Small>(numbers);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Container, typename Number>
|
||||||
|
typename std::enable_if<(sizeof(Number) <= 1), bool>::type
|
||||||
|
squeeze(const Container &)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Container, typename Number>
|
||||||
|
void assignNumbers(const Container &numbers)
|
||||||
|
{
|
||||||
|
Number *data;
|
||||||
|
m_dataLength = squeezable<size_t, quint16>(numbers.size()) ?
|
||||||
|
numbers.size() : std::numeric_limits<quint16>::max();
|
||||||
|
if (m_dataLength > sizeof(m_data) / sizeof(Number)) {
|
||||||
|
if (squeeze<Container, Number>(numbers))
|
||||||
|
return;
|
||||||
|
m_dataType = static_cast<Type>((sizeof(Number) * 8) | External);
|
||||||
|
m_data.external = malloc(m_dataLength * sizeof(Number));
|
||||||
|
data = static_cast<Number *>(m_data.external);
|
||||||
|
} else {
|
||||||
|
m_dataType = static_cast<Type>(sizeof(Number) * 8);
|
||||||
|
data = static_cast<Number *>(m_dataType & External ? m_data.external : &m_data);
|
||||||
|
}
|
||||||
|
quint16 i = 0; // If you really have more than 64k items, this will wrap. Too bad.
|
||||||
|
foreach (Number item, numbers)
|
||||||
|
data[i++] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearPointer()
|
||||||
|
{
|
||||||
|
if (m_dataType & External)
|
||||||
|
free(m_data.external);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -39,6 +39,7 @@ SOURCES += \
|
|||||||
qmlprofilertracefile.cpp \
|
qmlprofilertracefile.cpp \
|
||||||
qmlprofilertraceview.cpp \
|
qmlprofilertraceview.cpp \
|
||||||
qmlprofilerviewmanager.cpp \
|
qmlprofilerviewmanager.cpp \
|
||||||
|
qmltypedevent.cpp \
|
||||||
scenegraphtimelinemodel.cpp
|
scenegraphtimelinemodel.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
@@ -84,6 +85,7 @@ HEADERS += \
|
|||||||
qmlprofilertracefile.h \
|
qmlprofilertracefile.h \
|
||||||
qmlprofilertraceview.h \
|
qmlprofilertraceview.h \
|
||||||
qmlprofilerviewmanager.h \
|
qmlprofilerviewmanager.h \
|
||||||
|
qmltypedevent.h \
|
||||||
scenegraphtimelinemodel.h
|
scenegraphtimelinemodel.h
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
|
@@ -59,6 +59,7 @@ QtcPlugin {
|
|||||||
"qmlprofilertracefile.cpp", "qmlprofilertracefile.h",
|
"qmlprofilertracefile.cpp", "qmlprofilertracefile.h",
|
||||||
"qmlprofilertraceview.cpp", "qmlprofilertraceview.h",
|
"qmlprofilertraceview.cpp", "qmlprofilertraceview.h",
|
||||||
"qmlprofilerviewmanager.cpp", "qmlprofilerviewmanager.h",
|
"qmlprofilerviewmanager.cpp", "qmlprofilerviewmanager.h",
|
||||||
|
"qmltypedevent.cpp", "qmltypedevent.h",
|
||||||
"scenegraphtimelinemodel.cpp", "scenegraphtimelinemodel.h",
|
"scenegraphtimelinemodel.cpp", "scenegraphtimelinemodel.h",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@@ -78,10 +78,10 @@ void QmlProfilerAnimationsModel::loadData()
|
|||||||
if (!accepted(type))
|
if (!accepted(type))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
lastThread = (AnimationThread)event.numericData(2);
|
lastThread = (AnimationThread)event.number<qint32>(2);
|
||||||
|
|
||||||
// initial estimation of the event duration: 1/framerate
|
// initial estimation of the event duration: 1/framerate
|
||||||
qint64 estimatedDuration = event.numericData(0) > 0 ? 1e9/event.numericData(0) : 1;
|
qint64 estimatedDuration = event.number<qint32>(0) > 0 ? 1e9 / event.number<qint32>(0) : 1;
|
||||||
|
|
||||||
// the profiler registers the animation events at the end of them
|
// the profiler registers the animation events at the end of them
|
||||||
qint64 realEndTime = event.timestamp();
|
qint64 realEndTime = event.timestamp();
|
||||||
@@ -97,8 +97,8 @@ void QmlProfilerAnimationsModel::loadData()
|
|||||||
// Don't "fix" the framerate even if we've fixed the duration.
|
// Don't "fix" the framerate even if we've fixed the duration.
|
||||||
// The server should know better after all and if it doesn't we want to see that.
|
// The server should know better after all and if it doesn't we want to see that.
|
||||||
lastEvent.typeId = event.typeIndex();
|
lastEvent.typeId = event.typeIndex();
|
||||||
lastEvent.framerate = (int)event.numericData(0);
|
lastEvent.framerate = event.number<qint32>(0);
|
||||||
lastEvent.animationcount = (int)event.numericData(1);
|
lastEvent.animationcount = event.number<qint32>(1);
|
||||||
QTC_ASSERT(lastEvent.animationcount > 0, continue);
|
QTC_ASSERT(lastEvent.animationcount > 0, continue);
|
||||||
|
|
||||||
m_data.insert(insert(realStartTime, realEndTime - realStartTime, lastThread), lastEvent);
|
m_data.insert(insert(realStartTime, realEndTime - realStartTime, lastThread), lastEvent);
|
||||||
|
@@ -248,7 +248,7 @@ void QmlProfilerDataModel::addEvent(Message message, RangeType rangeType, int de
|
|||||||
message == DebugMessage ? QString() : data);
|
message == DebugMessage ? QString() : data);
|
||||||
QmlEvent eventData = (message == DebugMessage) ?
|
QmlEvent eventData = (message == DebugMessage) ?
|
||||||
QmlEvent(startTime, duration, -1, data) :
|
QmlEvent(startTime, duration, -1, data) :
|
||||||
QmlEvent(startTime, duration, -1, ndata1, ndata2, ndata3, ndata4, ndata5);
|
QmlEvent(startTime, duration, -1, {ndata1, ndata2, ndata3, ndata4, ndata5});
|
||||||
|
|
||||||
QHash<QmlEventType, int>::Iterator it = d->eventTypeIds.find(typeData);
|
QHash<QmlEventType, int>::Iterator it = d->eventTypeIds.find(typeData);
|
||||||
if (it != d->eventTypeIds.end()) {
|
if (it != d->eventTypeIds.end()) {
|
||||||
|
@@ -360,7 +360,7 @@ void QmlProfilerFileReader::loadEvents(QXmlStreamReader &stream)
|
|||||||
case QXmlStreamReader::StartElement: {
|
case QXmlStreamReader::StartElement: {
|
||||||
if (elementName == _("range")) {
|
if (elementName == _("range")) {
|
||||||
progress(stream.device());
|
progress(stream.device());
|
||||||
QmlEvent event(0, 0, -1, 0, 0, 0, 0, 0);
|
QmlEvent event;
|
||||||
|
|
||||||
const QXmlStreamAttributes attributes = stream.attributes();
|
const QXmlStreamAttributes attributes = stream.attributes();
|
||||||
if (!attributes.hasAttribute(_("startTime"))
|
if (!attributes.hasAttribute(_("startTime"))
|
||||||
@@ -375,37 +375,37 @@ void QmlProfilerFileReader::loadEvents(QXmlStreamReader &stream)
|
|||||||
|
|
||||||
// attributes for special events
|
// attributes for special events
|
||||||
if (attributes.hasAttribute(_("framerate")))
|
if (attributes.hasAttribute(_("framerate")))
|
||||||
event.setNumericData(0, attributes.value(_("framerate")).toLongLong());
|
event.setNumber<qint32>(0, attributes.value(_("framerate")).toInt());
|
||||||
if (attributes.hasAttribute(_("animationcount")))
|
if (attributes.hasAttribute(_("animationcount")))
|
||||||
event.setNumericData(1, attributes.value(_("animationcount")).toLongLong());
|
event.setNumber<qint32>(1, attributes.value(_("animationcount")).toInt());
|
||||||
if (attributes.hasAttribute(_("thread")))
|
if (attributes.hasAttribute(_("thread")))
|
||||||
event.setNumericData(2, attributes.value(_("thread")).toLongLong());
|
event.setNumber<qint32>(2, attributes.value(_("thread")).toInt());
|
||||||
if (attributes.hasAttribute(_("width")))
|
if (attributes.hasAttribute(_("width")))
|
||||||
event.setNumericData(0, attributes.value(_("width")).toLongLong());
|
event.setNumber<qint32>(0, attributes.value(_("width")).toInt());
|
||||||
if (attributes.hasAttribute(_("height")))
|
if (attributes.hasAttribute(_("height")))
|
||||||
event.setNumericData(1, attributes.value(_("height")).toLongLong());
|
event.setNumber<qint32>(1, attributes.value(_("height")).toInt());
|
||||||
if (attributes.hasAttribute(_("refCount")))
|
if (attributes.hasAttribute(_("refCount")))
|
||||||
event.setNumericData(2, attributes.value(_("refCount")).toLongLong());
|
event.setNumber<qint32>(2, attributes.value(_("refCount")).toInt());
|
||||||
if (attributes.hasAttribute(_("amount")))
|
if (attributes.hasAttribute(_("amount")))
|
||||||
event.setNumericData(0, attributes.value(_("amount")).toLongLong());
|
event.setNumber<qint64>(0, attributes.value(_("amount")).toLongLong());
|
||||||
if (attributes.hasAttribute(_("timing1")))
|
if (attributes.hasAttribute(_("timing1")))
|
||||||
event.setNumericData(0, attributes.value(_("timing1")).toLongLong());
|
event.setNumber<qint64>(0, attributes.value(_("timing1")).toLongLong());
|
||||||
if (attributes.hasAttribute(_("timing2")))
|
if (attributes.hasAttribute(_("timing2")))
|
||||||
event.setNumericData(1, attributes.value(_("timing2")).toLongLong());
|
event.setNumber<qint64>(1, attributes.value(_("timing2")).toLongLong());
|
||||||
if (attributes.hasAttribute(_("timing3")))
|
if (attributes.hasAttribute(_("timing3")))
|
||||||
event.setNumericData(2, attributes.value(_("timing3")).toLongLong());
|
event.setNumber<qint64>(2, attributes.value(_("timing3")).toLongLong());
|
||||||
if (attributes.hasAttribute(_("timing4")))
|
if (attributes.hasAttribute(_("timing4")))
|
||||||
event.setNumericData(3, attributes.value(_("timing4")).toLongLong());
|
event.setNumber<qint64>(3, attributes.value(_("timing4")).toLongLong());
|
||||||
if (attributes.hasAttribute(_("timing5")))
|
if (attributes.hasAttribute(_("timing5")))
|
||||||
event.setNumericData(4, attributes.value(_("timing5")).toLongLong());
|
event.setNumber<qint64>(4, attributes.value(_("timing5")).toLongLong());
|
||||||
if (attributes.hasAttribute(_("type")))
|
if (attributes.hasAttribute(_("type")))
|
||||||
event.setNumericData(0, attributes.value(_("type")).toLongLong());
|
event.setNumber<qint32>(0, attributes.value(_("type")).toInt());
|
||||||
if (attributes.hasAttribute(_("data1")))
|
if (attributes.hasAttribute(_("data1")))
|
||||||
event.setNumericData(1, attributes.value(_("data1")).toLongLong());
|
event.setNumber<qint32>(1, attributes.value(_("data1")).toInt());
|
||||||
if (attributes.hasAttribute(_("data2")))
|
if (attributes.hasAttribute(_("data2")))
|
||||||
event.setNumericData(2, attributes.value(_("data2")).toLongLong());
|
event.setNumber<qint32>(2, attributes.value(_("data2")).toInt());
|
||||||
if (attributes.hasAttribute(_("text")))
|
if (attributes.hasAttribute(_("text")))
|
||||||
event.setStringData(attributes.value(_("text")).toString());
|
event.setString(attributes.value(_("text")).toString());
|
||||||
|
|
||||||
event.setTypeIndex(attributes.value(_("eventIndex")).toInt());
|
event.setTypeIndex(attributes.value(_("eventIndex")).toInt());
|
||||||
|
|
||||||
@@ -601,49 +601,47 @@ void QmlProfilerFileWriter::save(QIODevice *device)
|
|||||||
if (type.message == Event) {
|
if (type.message == Event) {
|
||||||
if (type.detailType == AnimationFrame) {
|
if (type.detailType == AnimationFrame) {
|
||||||
// special: animation event
|
// special: animation event
|
||||||
stream.writeAttribute(_("framerate"), QString::number(event.numericData(0)));
|
stream.writeAttribute(_("framerate"), QString::number(event.number<qint32>(0)));
|
||||||
stream.writeAttribute(_("animationcount"), QString::number(event.numericData(1)));
|
stream.writeAttribute(_("animationcount"),
|
||||||
stream.writeAttribute(_("thread"), QString::number(event.numericData(2)));
|
QString::number(event.number<qint32>(1)));
|
||||||
|
stream.writeAttribute(_("thread"), QString::number(event.number<qint32>(2)));
|
||||||
} else if (type.detailType == Key || type.detailType == Mouse) {
|
} else if (type.detailType == Key || type.detailType == Mouse) {
|
||||||
// special: input event
|
// special: input event
|
||||||
stream.writeAttribute(_("type"), QString::number(event.numericData(0)));
|
stream.writeAttribute(_("type"), QString::number(event.number<qint32>(0)));
|
||||||
stream.writeAttribute(_("data1"), QString::number(event.numericData(1)));
|
stream.writeAttribute(_("data1"), QString::number(event.number<qint32>(1)));
|
||||||
stream.writeAttribute(_("data2"), QString::number(event.numericData(2)));
|
stream.writeAttribute(_("data2"), QString::number(event.number<qint32>(2)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// special: pixmap cache event
|
// special: pixmap cache event
|
||||||
if (type.message == PixmapCacheEvent) {
|
if (type.message == PixmapCacheEvent) {
|
||||||
if (type.detailType == PixmapSizeKnown) {
|
if (type.detailType == PixmapSizeKnown) {
|
||||||
stream.writeAttribute(_("width"), QString::number(event.numericData(0)));
|
stream.writeAttribute(_("width"), QString::number(event.number<qint32>(0)));
|
||||||
stream.writeAttribute(_("height"), QString::number(event.numericData(1)));
|
stream.writeAttribute(_("height"), QString::number(event.number<qint32>(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type.detailType == PixmapReferenceCountChanged ||
|
if (type.detailType == PixmapReferenceCountChanged ||
|
||||||
type.detailType == PixmapCacheCountChanged)
|
type.detailType == PixmapCacheCountChanged)
|
||||||
stream.writeAttribute(_("refCount"), QString::number(event.numericData(2)));
|
stream.writeAttribute(_("refCount"), QString::number(event.number<qint32>(2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type.message == SceneGraphFrame) {
|
if (type.message == SceneGraphFrame) {
|
||||||
// special: scenegraph frame events
|
// special: scenegraph frame events
|
||||||
if (event.numericData(0) > 0)
|
for (int i = 0; i < 5; ++i) {
|
||||||
stream.writeAttribute(_("timing1"), QString::number(event.numericData(0)));
|
qint64 number = event.number<qint64>(i);
|
||||||
if (event.numericData(1) > 0)
|
if (number <= 0)
|
||||||
stream.writeAttribute(_("timing2"), QString::number(event.numericData(1)));
|
continue;
|
||||||
if (event.numericData(2) > 0)
|
stream.writeAttribute(QString::fromLatin1("timing%1").arg(i + 1),
|
||||||
stream.writeAttribute(_("timing3"), QString::number(event.numericData(2)));
|
QString::number(number));
|
||||||
if (event.numericData(3) > 0)
|
}
|
||||||
stream.writeAttribute(_("timing4"), QString::number(event.numericData(3)));
|
|
||||||
if (event.numericData(4) > 0)
|
|
||||||
stream.writeAttribute(_("timing5"), QString::number(event.numericData(4)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// special: memory allocation event
|
// special: memory allocation event
|
||||||
if (type.message == MemoryAllocation)
|
if (type.message == MemoryAllocation)
|
||||||
stream.writeAttribute(_("amount"), QString::number(event.numericData(0)));
|
stream.writeAttribute(_("amount"), QString::number(event.number<qint64>(0)));
|
||||||
|
|
||||||
if (type.message == DebugMessage)
|
if (type.message == DebugMessage)
|
||||||
stream.writeAttribute(_("text"), event.stringData());
|
stream.writeAttribute(_("text"), event.string());
|
||||||
|
|
||||||
stream.writeEndElement();
|
stream.writeEndElement();
|
||||||
incrementProgress();
|
incrementProgress();
|
||||||
|
203
src/plugins/qmlprofiler/qmltypedevent.cpp
Normal file
203
src/plugins/qmlprofiler/qmltypedevent.cpp
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "qmltypedevent.h"
|
||||||
|
#include <QVarLengthArray>
|
||||||
|
|
||||||
|
namespace QmlProfiler {
|
||||||
|
|
||||||
|
QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
|
||||||
|
{
|
||||||
|
qint64 time;
|
||||||
|
qint32 messageType;
|
||||||
|
qint32 subtype;
|
||||||
|
|
||||||
|
stream >> time >> messageType;
|
||||||
|
|
||||||
|
RangeType rangeType = MaximumRangeType;
|
||||||
|
if (!stream.atEnd()) {
|
||||||
|
stream >> subtype;
|
||||||
|
rangeType = static_cast<RangeType>(subtype);
|
||||||
|
} else {
|
||||||
|
subtype = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.event.setTimestamp(time);
|
||||||
|
event.event.setTypeIndex(-1);
|
||||||
|
event.type.displayName.clear();
|
||||||
|
event.type.data.clear();
|
||||||
|
event.type.location.filename.clear();
|
||||||
|
event.type.location.line = event.type.location.column = -1;
|
||||||
|
|
||||||
|
switch (messageType) {
|
||||||
|
case Event: {
|
||||||
|
event.type.detailType = subtype;
|
||||||
|
event.type.rangeType = MaximumRangeType;
|
||||||
|
event.type.message = static_cast<Message>(messageType);
|
||||||
|
switch (subtype) {
|
||||||
|
case StartTrace:
|
||||||
|
case EndTrace: {
|
||||||
|
QVarLengthArray<qint32> engineIds;
|
||||||
|
while (!stream.atEnd()) {
|
||||||
|
qint32 id;
|
||||||
|
stream >> id;
|
||||||
|
engineIds << id;
|
||||||
|
}
|
||||||
|
event.event.setNumbers<QVarLengthArray<qint32>, qint32>(engineIds);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AnimationFrame: {
|
||||||
|
qint32 frameRate, animationCount;
|
||||||
|
qint32 threadId;
|
||||||
|
stream >> frameRate >> animationCount;
|
||||||
|
if (!stream.atEnd())
|
||||||
|
stream >> threadId;
|
||||||
|
else
|
||||||
|
threadId = 0;
|
||||||
|
|
||||||
|
event.event.setNumbers<qint32>({frameRate, animationCount, threadId});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Mouse:
|
||||||
|
case Key:
|
||||||
|
int inputType = (subtype == Key ? InputKeyUnknown : InputMouseUnknown);
|
||||||
|
if (!stream.atEnd())
|
||||||
|
stream >> inputType;
|
||||||
|
qint32 a = -1;
|
||||||
|
if (!stream.atEnd())
|
||||||
|
stream >> a;
|
||||||
|
qint32 b = -1;
|
||||||
|
if (!stream.atEnd())
|
||||||
|
stream >> b;
|
||||||
|
|
||||||
|
event.event.setNumbers<qint32>({inputType, a, b});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Complete: {
|
||||||
|
event.type.message = static_cast<Message>(messageType);
|
||||||
|
event.type.rangeType = MaximumRangeType;
|
||||||
|
event.type.detailType = subtype;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SceneGraphFrame: {
|
||||||
|
QVarLengthArray<qint64> params;
|
||||||
|
qint64 param;
|
||||||
|
|
||||||
|
while (!stream.atEnd()) {
|
||||||
|
stream >> param;
|
||||||
|
params.push_back(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
event.type.message = static_cast<Message>(messageType);
|
||||||
|
event.type.rangeType = MaximumRangeType;
|
||||||
|
event.type.detailType = subtype;
|
||||||
|
event.event.setNumbers<QVarLengthArray<qint64>, qint64>(params);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PixmapCacheEvent: {
|
||||||
|
qint32 width = 0, height = 0, refcount = 0;
|
||||||
|
stream >> event.type.location.filename;
|
||||||
|
if (subtype == PixmapReferenceCountChanged || subtype == PixmapCacheCountChanged) {
|
||||||
|
stream >> refcount;
|
||||||
|
} else if (subtype == PixmapSizeKnown) {
|
||||||
|
stream >> width >> height;
|
||||||
|
refcount = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.type.message = static_cast<Message>(messageType);
|
||||||
|
event.type.rangeType = MaximumRangeType;
|
||||||
|
event.type.location.line = event.type.location.column = 0;
|
||||||
|
event.type.detailType = subtype;
|
||||||
|
event.event.setNumbers<qint32>({width, height, refcount});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MemoryAllocation: {
|
||||||
|
qint64 delta;
|
||||||
|
stream >> delta;
|
||||||
|
|
||||||
|
event.type.message = static_cast<Message>(messageType);
|
||||||
|
event.type.rangeType = MaximumRangeType;
|
||||||
|
event.type.detailType = subtype;
|
||||||
|
event.event.setNumbers<qint64>({delta});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RangeStart: {
|
||||||
|
// read and ignore binding type
|
||||||
|
if (rangeType == Binding && !stream.atEnd()) {
|
||||||
|
qint32 bindingType;
|
||||||
|
stream >> bindingType;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.type.message = MaximumMessage;
|
||||||
|
event.type.rangeType = rangeType;
|
||||||
|
event.event.setRangeStage(RangeStart);
|
||||||
|
event.type.detailType = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RangeData: {
|
||||||
|
stream >> event.type.data;
|
||||||
|
|
||||||
|
event.type.message = MaximumMessage;
|
||||||
|
event.type.rangeType = rangeType;
|
||||||
|
event.event.setRangeStage(RangeData);
|
||||||
|
event.type.detailType = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RangeLocation: {
|
||||||
|
stream >> event.type.location.filename
|
||||||
|
>> static_cast<qint32 &>(event.type.location.line);
|
||||||
|
|
||||||
|
if (!stream.atEnd())
|
||||||
|
stream >> static_cast<qint32 &>(event.type.location.column);
|
||||||
|
else
|
||||||
|
event.type.location.column = -1;
|
||||||
|
|
||||||
|
event.type.message = MaximumMessage;
|
||||||
|
event.type.rangeType = rangeType;
|
||||||
|
event.event.setRangeStage(RangeLocation);
|
||||||
|
event.type.detailType = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case RangeEnd: {
|
||||||
|
event.type.message = MaximumMessage;
|
||||||
|
event.type.rangeType = rangeType;
|
||||||
|
event.event.setRangeStage(RangeEnd);
|
||||||
|
event.type.detailType = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
event.type.message = static_cast<Message>(messageType);
|
||||||
|
event.type.rangeType = MaximumRangeType;
|
||||||
|
event.type.detailType = subtype;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QmlProfiler
|
42
src/plugins/qmlprofiler/qmltypedevent.h
Normal file
42
src/plugins/qmlprofiler/qmltypedevent.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "qmlevent.h"
|
||||||
|
#include "qmleventtype.h"
|
||||||
|
|
||||||
|
#include <QDataStream>
|
||||||
|
|
||||||
|
namespace QmlProfiler {
|
||||||
|
|
||||||
|
struct QmlTypedEvent
|
||||||
|
{
|
||||||
|
QmlEvent event;
|
||||||
|
QmlEventType type;
|
||||||
|
};
|
||||||
|
|
||||||
|
QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event);
|
||||||
|
|
||||||
|
} // namespace QmlProfiler
|
@@ -150,71 +150,79 @@ void SceneGraphTimelineModel::loadData()
|
|||||||
// look incomplete if that was left out as the printf profiler lists it, too, and people
|
// look incomplete if that was left out as the printf profiler lists it, too, and people
|
||||||
// are apparently comparing that. Unfortunately it is somewhat redundant as the other
|
// are apparently comparing that. Unfortunately it is somewhat redundant as the other
|
||||||
// parts of the breakdown are usually very short.
|
// parts of the breakdown are usually very short.
|
||||||
qint64 startTime = event.timestamp() - event.numericData(0) - event.numericData(1) -
|
qint64 startTime = event.timestamp() - event.number<qint64>(0) - event.number<qint64>(1)
|
||||||
event.numericData(2) - event.numericData(3);
|
- event.number<qint64>(2) - event.number<qint64>(3);
|
||||||
startTime += insert(startTime, event.numericData(0), event.typeIndex(), RenderPreprocess);
|
startTime += insert(startTime, event.number<qint64>(0), event.typeIndex(),
|
||||||
startTime += insert(startTime, event.numericData(1), event.typeIndex(), RenderUpdate);
|
RenderPreprocess);
|
||||||
startTime += insert(startTime, event.numericData(2), event.typeIndex(), RenderBind);
|
startTime += insert(startTime, event.number<qint64>(1), event.typeIndex(),
|
||||||
insert(startTime, event.numericData(3), event.typeIndex(), RenderRender);
|
RenderUpdate);
|
||||||
|
startTime += insert(startTime, event.number<qint64>(2), event.typeIndex(), RenderBind);
|
||||||
|
insert(startTime, event.number<qint64>(3), event.typeIndex(), RenderRender);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SceneGraphAdaptationLayerFrame: {
|
case SceneGraphAdaptationLayerFrame: {
|
||||||
qint64 startTime = event.timestamp() - event.numericData(1) - event.numericData(2);
|
qint64 startTime = event.timestamp() - event.number<qint64>(1)
|
||||||
startTime += insert(startTime, event.numericData(1), event.typeIndex(), GlyphRender,
|
- event.number<qint64>(2);
|
||||||
event.numericData(0));
|
startTime += insert(startTime, event.number<qint64>(1), event.typeIndex(), GlyphRender,
|
||||||
insert(startTime, event.numericData(2), event.typeIndex(), GlyphStore, event.numericData(0));
|
event.number<qint64>(0));
|
||||||
|
insert(startTime, event.number<qint64>(2), event.typeIndex(), GlyphStore,
|
||||||
|
event.number<qint64>(0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SceneGraphContextFrame: {
|
case SceneGraphContextFrame: {
|
||||||
insert(event.timestamp() - event.numericData(0), event.numericData(0), event.typeIndex(),
|
insert(event.timestamp() - event.number<qint64>(0), event.number<qint64>(0),
|
||||||
Material);
|
event.typeIndex(), Material);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SceneGraphRenderLoopFrame: {
|
case SceneGraphRenderLoopFrame: {
|
||||||
qint64 startTime = event.timestamp() - event.numericData(0) - event.numericData(1) -
|
qint64 startTime = event.timestamp() - event.number<qint64>(0) - event.number<qint64>(1)
|
||||||
event.numericData(2);
|
- event.number<qint64>(2);
|
||||||
startTime += insert(startTime, event.numericData(0), event.typeIndex(),
|
startTime += insert(startTime, event.number<qint64>(0), event.typeIndex(),
|
||||||
RenderThreadSync);
|
RenderThreadSync);
|
||||||
startTime += insert(startTime, event.numericData(1), event.typeIndex(),
|
startTime += insert(startTime, event.number<qint64>(1), event.typeIndex(),
|
||||||
Render);
|
Render);
|
||||||
insert(startTime, event.numericData(2), event.typeIndex(), Swap);
|
insert(startTime, event.number<qint64>(2), event.typeIndex(), Swap);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SceneGraphTexturePrepare: {
|
case SceneGraphTexturePrepare: {
|
||||||
qint64 startTime = event.timestamp() - event.numericData(0) - event.numericData(1) -
|
qint64 startTime = event.timestamp() - event.number<qint64>(0) - event.number<qint64>(1)
|
||||||
event.numericData(2) - event.numericData(3) - event.numericData(4);
|
- event.number<qint64>(2) - event.number<qint64>(3) - event.number<qint64>(4);
|
||||||
startTime += insert(startTime, event.numericData(0), event.typeIndex(), TextureBind);
|
startTime += insert(startTime, event.number<qint64>(0), event.typeIndex(), TextureBind);
|
||||||
startTime += insert(startTime, event.numericData(1), event.typeIndex(), TextureConvert);
|
startTime += insert(startTime, event.number<qint64>(1), event.typeIndex(),
|
||||||
startTime += insert(startTime, event.numericData(2), event.typeIndex(), TextureSwizzle);
|
TextureConvert);
|
||||||
startTime += insert(startTime, event.numericData(3), event.typeIndex(), TextureUpload);
|
startTime += insert(startTime, event.number<qint64>(2), event.typeIndex(),
|
||||||
insert(startTime, event.numericData(4), event.typeIndex(), TextureMipmap);
|
TextureSwizzle);
|
||||||
|
startTime += insert(startTime, event.number<qint64>(3), event.typeIndex(),
|
||||||
|
TextureUpload);
|
||||||
|
insert(startTime, event.number<qint64>(4), event.typeIndex(), TextureMipmap);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SceneGraphTextureDeletion: {
|
case SceneGraphTextureDeletion: {
|
||||||
insert(event.timestamp() - event.numericData(0), event.numericData(0), event.typeIndex(),
|
insert(event.timestamp() - event.number<qint64>(0), event.number<qint64>(0),
|
||||||
TextureDeletion);
|
event.typeIndex(), TextureDeletion);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SceneGraphPolishAndSync: {
|
case SceneGraphPolishAndSync: {
|
||||||
qint64 startTime = event.timestamp() - event.numericData(0) - event.numericData(1) -
|
qint64 startTime = event.timestamp() - event.number<qint64>(0) - event.number<qint64>(1)
|
||||||
event.numericData(2) - event.numericData(3);
|
- event.number<qint64>(2) - event.number<qint64>(3);
|
||||||
|
|
||||||
startTime += insert(startTime, event.numericData(0), event.typeIndex(), Polish);
|
startTime += insert(startTime, event.number<qint64>(0), event.typeIndex(), Polish);
|
||||||
startTime += insert(startTime, event.numericData(1), event.typeIndex(), Wait);
|
startTime += insert(startTime, event.number<qint64>(1), event.typeIndex(), Wait);
|
||||||
startTime += insert(startTime, event.numericData(2), event.typeIndex(), GUIThreadSync);
|
startTime += insert(startTime, event.number<qint64>(2), event.typeIndex(),
|
||||||
insert(startTime, event.numericData(3), event.typeIndex(), Animations);
|
GUIThreadSync);
|
||||||
|
insert(startTime, event.number<qint64>(3), event.typeIndex(), Animations);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SceneGraphWindowsAnimations: {
|
case SceneGraphWindowsAnimations: {
|
||||||
// GUI thread, separate animations stage
|
// GUI thread, separate animations stage
|
||||||
insert(event.timestamp() - event.numericData(0), event.numericData(0), event.typeIndex(),
|
insert(event.timestamp() - event.number<qint64>(0), event.number<qint64>(0),
|
||||||
Animations);
|
event.typeIndex(), Animations);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SceneGraphPolishFrame: {
|
case SceneGraphPolishFrame: {
|
||||||
// GUI thread, separate polish stage
|
// GUI thread, separate polish stage
|
||||||
insert(event.timestamp() - event.numericData(0), event.numericData(0), event.typeIndex(),
|
insert(event.timestamp() - event.number<qint64>(0), event.number<qint64>(0),
|
||||||
Polish);
|
event.typeIndex(), Polish);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
|
Reference in New Issue
Block a user