forked from qt-creator/qt-creator
PerfProfiler: Support multiple attributes per sample
Change-Id: I0c457eb05a354588eab25bbfde9e3470183fe9d3 Reviewed-by: Milian Wolff <milian.wolff@kdab.com> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
@@ -54,6 +54,10 @@ public:
|
|||||||
LastSpecialTypeId = -256
|
LastSpecialTypeId = -256
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int numAttributes() const { return m_values.length() + 1; }
|
||||||
|
qint32 attributeId(int i) const { return i == 0 ? typeIndex() : m_values[i - 1].first; }
|
||||||
|
quint64 attributeValue(int i) const { return i == 0 ? m_value : m_values[i - 1].second; }
|
||||||
|
|
||||||
const QVector<qint32> &origFrames() const { return m_origFrames; }
|
const QVector<qint32> &origFrames() const { return m_origFrames; }
|
||||||
quint8 origNumGuessedFrames() const { return m_origNumGuessedFrames; }
|
quint8 origNumGuessedFrames() const { return m_origNumGuessedFrames; }
|
||||||
|
|
||||||
@@ -68,9 +72,6 @@ public:
|
|||||||
quint8 numGuessedFrames() const { return m_numGuessedFrames; }
|
quint8 numGuessedFrames() const { return m_numGuessedFrames; }
|
||||||
void setNumGuessedFrames(quint8 numGuessedFrames) { m_numGuessedFrames = numGuessedFrames; }
|
void setNumGuessedFrames(quint8 numGuessedFrames) { m_numGuessedFrames = numGuessedFrames; }
|
||||||
|
|
||||||
quint64 period() const { return m_value; }
|
|
||||||
quint64 value() const { return m_value; }
|
|
||||||
|
|
||||||
quint8 feature() const { return m_feature; }
|
quint8 feature() const { return m_feature; }
|
||||||
|
|
||||||
quint8 extra() const { return m_extra; }
|
quint8 extra() const { return m_extra; }
|
||||||
@@ -80,6 +81,7 @@ private:
|
|||||||
friend QDataStream &operator>>(QDataStream &stream, PerfEvent &event);
|
friend QDataStream &operator>>(QDataStream &stream, PerfEvent &event);
|
||||||
friend QDataStream &operator<<(QDataStream &stream, const PerfEvent &event);
|
friend QDataStream &operator<<(QDataStream &stream, const PerfEvent &event);
|
||||||
|
|
||||||
|
QVector<QPair<qint32, quint64>> m_values;
|
||||||
QVector<qint32> m_origFrames;
|
QVector<qint32> m_origFrames;
|
||||||
QVector<qint32> m_frames;
|
QVector<qint32> m_frames;
|
||||||
QHash<qint32, QVariant> m_traceData;
|
QHash<qint32, QVariant> m_traceData;
|
||||||
@@ -140,20 +142,23 @@ inline QDataStream &operator>>(QDataStream &stream, PerfEvent &event)
|
|||||||
event.setExtra(isSwitchOut);
|
event.setExtra(isSwitchOut);
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
qint32 typeIndex;
|
qint32 firstAttributeId;
|
||||||
stream >> event.m_origFrames >> event.m_origNumGuessedFrames;
|
stream >> event.m_origFrames >> event.m_origNumGuessedFrames;
|
||||||
QVector<QPair<qint32, quint64>> values;
|
QVector<QPair<qint32, quint64>> values;
|
||||||
stream >> values;
|
stream >> values;
|
||||||
if (values.isEmpty()) {
|
if (values.isEmpty()) {
|
||||||
typeIndex = 0;
|
firstAttributeId = PerfEvent::LastSpecialTypeId;
|
||||||
} else {
|
} else {
|
||||||
typeIndex = values.first().first;
|
firstAttributeId = PerfEvent::LastSpecialTypeId - values.first().first;
|
||||||
event.m_value = values.first().second;
|
event.m_value = values.first().second;
|
||||||
// TODO: support multiple values per event.
|
for (auto it = values.constBegin() + 1, end = values.constEnd(); it != end; ++it) {
|
||||||
|
event.m_values.push_back({ PerfEvent::LastSpecialTypeId - it->first,
|
||||||
|
it->second });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (event.m_feature == PerfEventType::TracePointSample)
|
if (event.m_feature == PerfEventType::TracePointSample)
|
||||||
stream >> event.m_traceData;
|
stream >> event.m_traceData;
|
||||||
event.setTypeIndex(PerfEvent::LastSpecialTypeId - typeIndex);
|
event.setTypeIndex(firstAttributeId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,7 +183,10 @@ inline QDataStream &operator<<(QDataStream &stream, const PerfEvent &event)
|
|||||||
stream << event.m_origFrames << event.m_origNumGuessedFrames;
|
stream << event.m_origFrames << event.m_origNumGuessedFrames;
|
||||||
|
|
||||||
QVector<QPair<qint32, quint64>> values;
|
QVector<QPair<qint32, quint64>> values;
|
||||||
values.push_back({ PerfEvent::LastSpecialTypeId - event.typeIndex(), event.m_value });
|
for (int i = 0, end = event.numAttributes(); i < end; ++i) {
|
||||||
|
values.push_back({ PerfEvent::LastSpecialTypeId - event.attributeId(i),
|
||||||
|
event.attributeValue(i) });
|
||||||
|
}
|
||||||
stream << values;
|
stream << values;
|
||||||
|
|
||||||
if (feature == PerfEventType::TracePointSample)
|
if (feature == PerfEventType::TracePointSample)
|
||||||
|
@@ -227,8 +227,12 @@ void PerfProfilerFlameGraphData::updateTraceData(const PerfEvent &event, const P
|
|||||||
PerfProfilerFlameGraphModel::Data *data,
|
PerfProfilerFlameGraphModel::Data *data,
|
||||||
int numSamples)
|
int numSamples)
|
||||||
{
|
{
|
||||||
const PerfEventType::Attribute &attribute = type.attribute();
|
Q_UNUSED(type);
|
||||||
if (attribute.type == PerfEventType::TypeTracepoint) {
|
for (int i = 0, end = event.numAttributes(); i < end; ++i) {
|
||||||
|
const PerfEventType::Attribute &attribute = manager->attribute(event.attributeId(i));
|
||||||
|
if (attribute.type != PerfEventType::TypeTracepoint)
|
||||||
|
continue;
|
||||||
|
|
||||||
const PerfProfilerTraceManager::TracePoint &tracePoint
|
const PerfProfilerTraceManager::TracePoint &tracePoint
|
||||||
= manager->tracePoint(static_cast<int>(attribute.config));
|
= manager->tracePoint(static_cast<int>(attribute.config));
|
||||||
|
|
||||||
|
@@ -281,7 +281,7 @@ void PerfProfilerTraceManager::replayPerfEvents(PerfEventLoader loader, Initiali
|
|||||||
QTC_ASSERT(traceEvent.is<PerfEvent>(), return false);
|
QTC_ASSERT(traceEvent.is<PerfEvent>(), return false);
|
||||||
PerfEvent &&event = traceEvent.asRvalueRef<PerfEvent>();
|
PerfEvent &&event = traceEvent.asRvalueRef<PerfEvent>();
|
||||||
processSample(event);
|
processSample(event);
|
||||||
loader(event, eventType(event.typeIndex()));
|
loader(event, eventType(event.attributeId(0)));
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -167,8 +167,11 @@ QVariantMap PerfTimelineModel::details(int index) const
|
|||||||
const int guessedFrames = -frame.numSamples;
|
const int guessedFrames = -frame.numSamples;
|
||||||
if (guessedFrames > 0)
|
if (guessedFrames > 0)
|
||||||
result.insert(tr("Guessed"), tr("%n frames", nullptr, guessedFrames));
|
result.insert(tr("Guessed"), tr("%n frames", nullptr, guessedFrames));
|
||||||
if (const int sampleValue = value(index))
|
for (int i = 0, end = numAttributes(index); i < end; ++i) {
|
||||||
result.insert(tr("Value"), sampleValue);
|
const auto &name = orUnknown(manager->string(
|
||||||
|
manager->attribute(attributeId(index, i)).name));
|
||||||
|
result.insert(QString::fromUtf8(name), attributeValue(index, i));
|
||||||
|
}
|
||||||
if (attribute.type == PerfEventType::TypeTracepoint) {
|
if (attribute.type == PerfEventType::TypeTracepoint) {
|
||||||
const PerfProfilerTraceManager::TracePoint &tracePoint
|
const PerfProfilerTraceManager::TracePoint &tracePoint
|
||||||
= manager->tracePoint(static_cast<int>(attribute.config));
|
= manager->tracePoint(static_cast<int>(attribute.config));
|
||||||
@@ -283,8 +286,11 @@ float PerfTimelineModel::relativeHeight(int index) const
|
|||||||
void PerfTimelineModel::updateTraceData(const PerfEvent &event)
|
void PerfTimelineModel::updateTraceData(const PerfEvent &event)
|
||||||
{
|
{
|
||||||
const PerfProfilerTraceManager *manager = traceManager();
|
const PerfProfilerTraceManager *manager = traceManager();
|
||||||
const PerfEventType::Attribute &attribute = manager->attribute(event.typeIndex());
|
for (int i = 0; i < event.numAttributes(); ++i) {
|
||||||
if (attribute.type == PerfEventType::TypeTracepoint) {
|
const PerfEventType::Attribute &attribute = manager->attribute(event.attributeId(i));
|
||||||
|
if (attribute.type != PerfEventType::TypeTracepoint)
|
||||||
|
continue;
|
||||||
|
|
||||||
const PerfProfilerTraceManager::TracePoint &tracePoint
|
const PerfProfilerTraceManager::TracePoint &tracePoint
|
||||||
= manager->tracePoint(static_cast<int>(attribute.config));
|
= manager->tracePoint(static_cast<int>(attribute.config));
|
||||||
|
|
||||||
@@ -402,27 +408,30 @@ void PerfTimelineModel::updateFrames(const PerfEvent &event, int numConcurrentTh
|
|||||||
|
|
||||||
void PerfTimelineModel::addSample(const PerfEvent &event, qint64 resourceDelta, int resourceGuesses)
|
void PerfTimelineModel::addSample(const PerfEvent &event, qint64 resourceDelta, int resourceGuesses)
|
||||||
{
|
{
|
||||||
static const int intMax = std::numeric_limits<int>::max();
|
const int id = TimelineModel::insert(event.timestamp(), 1, event.attributeId(0));
|
||||||
const int value = static_cast<int>(qMin(static_cast<quint64>(intMax), event.value()));
|
|
||||||
|
|
||||||
const int id = TimelineModel::insert(event.timestamp(), 1, event.typeIndex());
|
|
||||||
StackFrame sample = StackFrame::sampleFrame();
|
StackFrame sample = StackFrame::sampleFrame();
|
||||||
|
sample.attributeValue = event.attributeValue(0);
|
||||||
sample.numSamples = event.numGuessedFrames() > 0 ? -event.numGuessedFrames() : 1;
|
sample.numSamples = event.numGuessedFrames() > 0 ? -event.numGuessedFrames() : 1;
|
||||||
sample.value = value;
|
|
||||||
sample.resourcePeak = m_resourceBlocks.currentTotal();
|
sample.resourcePeak = m_resourceBlocks.currentTotal();
|
||||||
sample.resourceDelta = resourceDelta;
|
sample.resourceDelta = resourceDelta;
|
||||||
sample.resourceGuesses = resourceGuesses;
|
sample.resourceGuesses = resourceGuesses;
|
||||||
|
sample.numAttributes = event.numAttributes();
|
||||||
m_data.insert(id, std::move(sample));
|
m_data.insert(id, std::move(sample));
|
||||||
const QHash<qint32, QVariant> &traceData = event.traceData();
|
const QHash<qint32, QVariant> &traceData = event.traceData();
|
||||||
if (!traceData.isEmpty())
|
if (!traceData.isEmpty())
|
||||||
m_extraData.insert(id, traceData);
|
m_extraData.insert(id, traceData);
|
||||||
|
|
||||||
|
for (int i = 1, end = sample.numAttributes; i < end; ++i) {
|
||||||
|
m_attributeValues[id].append(QPair<qint32, quint64>(event.attributeId(i),
|
||||||
|
event.attributeValue(i)));
|
||||||
|
}
|
||||||
|
|
||||||
m_lastTimestamp = event.timestamp();
|
m_lastTimestamp = event.timestamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerfTimelineModel::loadEvent(const PerfEvent &event, int numConcurrentThreads)
|
void PerfTimelineModel::loadEvent(const PerfEvent &event, int numConcurrentThreads)
|
||||||
{
|
{
|
||||||
switch (event.typeIndex()) {
|
switch (event.attributeId(0)) {
|
||||||
case PerfEvent::LostTypeId: {
|
case PerfEvent::LostTypeId: {
|
||||||
QVector<int> frames;
|
QVector<int> frames;
|
||||||
for (int pos = m_currentStack.length() - 1; pos >= 0; --pos)
|
for (int pos = m_currentStack.length() - 1; pos >= 0; --pos)
|
||||||
@@ -464,7 +473,7 @@ void PerfTimelineModel::loadEvent(const PerfEvent &event, int numConcurrentThrea
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
QTC_ASSERT(event.typeIndex() <= PerfEvent::LastSpecialTypeId, break);
|
QTC_ASSERT(event.attributeId(0) <= PerfEvent::LastSpecialTypeId, break);
|
||||||
|
|
||||||
if (event.timestamp() < 0) {
|
if (event.timestamp() < 0) {
|
||||||
updateTraceData(event);
|
updateTraceData(event);
|
||||||
@@ -608,9 +617,19 @@ float PerfTimelineModel::resourceUsage(int index) const
|
|||||||
: 0.0f;
|
: 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PerfTimelineModel::value(int index) const
|
qint32 PerfTimelineModel::attributeId(int index, int i) const
|
||||||
{
|
{
|
||||||
return m_data[index].value;
|
return (i == 0) ? selectionId(index) : m_attributeValues[index][i].first;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PerfTimelineModel::numAttributes(int index) const
|
||||||
|
{
|
||||||
|
return m_data[index].numAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 PerfTimelineModel::attributeValue(int index, int i) const
|
||||||
|
{
|
||||||
|
return (i == 0) ? m_data[index].attributeValue : m_attributeValues[index][i].second;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PerfTimelineModel::handlesTypeId(int typeId) const
|
bool PerfTimelineModel::handlesTypeId(int typeId) const
|
||||||
|
@@ -88,7 +88,9 @@ public:
|
|||||||
return selectionId(index) <= PerfEvent::LastSpecialTypeId;
|
return selectionId(index) <= PerfEvent::LastSpecialTypeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
int value(int index) const;
|
int numAttributes(int index) const;
|
||||||
|
qint32 attributeId(int index, int i) const;
|
||||||
|
quint64 attributeValue(int index, int i) const;
|
||||||
|
|
||||||
QHash<qint32, QVariant> extraData(int index) const { return m_extraData.value(index); }
|
QHash<qint32, QVariant> extraData(int index) const { return m_extraData.value(index); }
|
||||||
|
|
||||||
@@ -104,11 +106,12 @@ private:
|
|||||||
int numExpectedParallelSamples = 1;
|
int numExpectedParallelSamples = 1;
|
||||||
int displayRowCollapsed = MaximumSpecialRow;
|
int displayRowCollapsed = MaximumSpecialRow;
|
||||||
int displayRowExpanded = MaximumSpecialRow;
|
int displayRowExpanded = MaximumSpecialRow;
|
||||||
int value = 0;
|
|
||||||
|
|
||||||
|
quint64 attributeValue = 0;
|
||||||
qint64 resourcePeak = 0;
|
qint64 resourcePeak = 0;
|
||||||
qint64 resourceDelta = 0;
|
qint64 resourceDelta = 0;
|
||||||
int resourceGuesses = 0;
|
int resourceGuesses = 0;
|
||||||
|
int numAttributes = 0;
|
||||||
|
|
||||||
static StackFrame sampleFrame()
|
static StackFrame sampleFrame()
|
||||||
{
|
{
|
||||||
@@ -148,6 +151,7 @@ private:
|
|||||||
|
|
||||||
QVector<StackFrame> m_data;
|
QVector<StackFrame> m_data;
|
||||||
QHash<int, QHash<qint32, QVariant>> m_extraData;
|
QHash<int, QHash<qint32, QVariant>> m_extraData;
|
||||||
|
QHash<int, QVector<QPair<qint32, quint64>>> m_attributeValues;
|
||||||
|
|
||||||
void computeExpandedLevels();
|
void computeExpandedLevels();
|
||||||
const PerfProfilerTraceManager *traceManager() const;
|
const PerfProfilerTraceManager *traceManager() const;
|
||||||
|
Reference in New Issue
Block a user