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:
Ulf Hermann
2019-05-03 13:29:45 +02:00
parent 61fb66ab53
commit 5574884cb1
5 changed files with 62 additions and 27 deletions

View File

@@ -54,6 +54,10 @@ public:
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; }
quint8 origNumGuessedFrames() const { return m_origNumGuessedFrames; }
@@ -68,9 +72,6 @@ public:
quint8 numGuessedFrames() const { return m_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 extra() const { return m_extra; }
@@ -80,6 +81,7 @@ private:
friend QDataStream &operator>>(QDataStream &stream, PerfEvent &event);
friend QDataStream &operator<<(QDataStream &stream, const PerfEvent &event);
QVector<QPair<qint32, quint64>> m_values;
QVector<qint32> m_origFrames;
QVector<qint32> m_frames;
QHash<qint32, QVariant> m_traceData;
@@ -140,20 +142,23 @@ inline QDataStream &operator>>(QDataStream &stream, PerfEvent &event)
event.setExtra(isSwitchOut);
break;
default: {
qint32 typeIndex;
qint32 firstAttributeId;
stream >> event.m_origFrames >> event.m_origNumGuessedFrames;
QVector<QPair<qint32, quint64>> values;
stream >> values;
if (values.isEmpty()) {
typeIndex = 0;
firstAttributeId = PerfEvent::LastSpecialTypeId;
} else {
typeIndex = values.first().first;
firstAttributeId = PerfEvent::LastSpecialTypeId - values.first().first;
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)
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;
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;
if (feature == PerfEventType::TracePointSample)

View File

@@ -227,8 +227,12 @@ void PerfProfilerFlameGraphData::updateTraceData(const PerfEvent &event, const P
PerfProfilerFlameGraphModel::Data *data,
int numSamples)
{
const PerfEventType::Attribute &attribute = type.attribute();
if (attribute.type == PerfEventType::TypeTracepoint) {
Q_UNUSED(type);
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
= manager->tracePoint(static_cast<int>(attribute.config));

View File

@@ -281,7 +281,7 @@ void PerfProfilerTraceManager::replayPerfEvents(PerfEventLoader loader, Initiali
QTC_ASSERT(traceEvent.is<PerfEvent>(), return false);
PerfEvent &&event = traceEvent.asRvalueRef<PerfEvent>();
processSample(event);
loader(event, eventType(event.typeIndex()));
loader(event, eventType(event.attributeId(0)));
return true;
});

View File

@@ -167,8 +167,11 @@ QVariantMap PerfTimelineModel::details(int index) const
const int guessedFrames = -frame.numSamples;
if (guessedFrames > 0)
result.insert(tr("Guessed"), tr("%n frames", nullptr, guessedFrames));
if (const int sampleValue = value(index))
result.insert(tr("Value"), sampleValue);
for (int i = 0, end = numAttributes(index); i < end; ++i) {
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) {
const PerfProfilerTraceManager::TracePoint &tracePoint
= manager->tracePoint(static_cast<int>(attribute.config));
@@ -283,8 +286,11 @@ float PerfTimelineModel::relativeHeight(int index) const
void PerfTimelineModel::updateTraceData(const PerfEvent &event)
{
const PerfProfilerTraceManager *manager = traceManager();
const PerfEventType::Attribute &attribute = manager->attribute(event.typeIndex());
if (attribute.type == PerfEventType::TypeTracepoint) {
for (int i = 0; i < event.numAttributes(); ++i) {
const PerfEventType::Attribute &attribute = manager->attribute(event.attributeId(i));
if (attribute.type != PerfEventType::TypeTracepoint)
continue;
const PerfProfilerTraceManager::TracePoint &tracePoint
= 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)
{
static const int intMax = std::numeric_limits<int>::max();
const int value = static_cast<int>(qMin(static_cast<quint64>(intMax), event.value()));
const int id = TimelineModel::insert(event.timestamp(), 1, event.typeIndex());
const int id = TimelineModel::insert(event.timestamp(), 1, event.attributeId(0));
StackFrame sample = StackFrame::sampleFrame();
sample.attributeValue = event.attributeValue(0);
sample.numSamples = event.numGuessedFrames() > 0 ? -event.numGuessedFrames() : 1;
sample.value = value;
sample.resourcePeak = m_resourceBlocks.currentTotal();
sample.resourceDelta = resourceDelta;
sample.resourceGuesses = resourceGuesses;
sample.numAttributes = event.numAttributes();
m_data.insert(id, std::move(sample));
const QHash<qint32, QVariant> &traceData = event.traceData();
if (!traceData.isEmpty())
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();
}
void PerfTimelineModel::loadEvent(const PerfEvent &event, int numConcurrentThreads)
{
switch (event.typeIndex()) {
switch (event.attributeId(0)) {
case PerfEvent::LostTypeId: {
QVector<int> frames;
for (int pos = m_currentStack.length() - 1; pos >= 0; --pos)
@@ -464,7 +473,7 @@ void PerfTimelineModel::loadEvent(const PerfEvent &event, int numConcurrentThrea
break;
}
default: {
QTC_ASSERT(event.typeIndex() <= PerfEvent::LastSpecialTypeId, break);
QTC_ASSERT(event.attributeId(0) <= PerfEvent::LastSpecialTypeId, break);
if (event.timestamp() < 0) {
updateTraceData(event);
@@ -608,9 +617,19 @@ float PerfTimelineModel::resourceUsage(int index) const
: 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

View File

@@ -88,7 +88,9 @@ public:
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); }
@@ -104,11 +106,12 @@ private:
int numExpectedParallelSamples = 1;
int displayRowCollapsed = MaximumSpecialRow;
int displayRowExpanded = MaximumSpecialRow;
int value = 0;
quint64 attributeValue = 0;
qint64 resourcePeak = 0;
qint64 resourceDelta = 0;
int resourceGuesses = 0;
int numAttributes = 0;
static StackFrame sampleFrame()
{
@@ -148,6 +151,7 @@ private:
QVector<StackFrame> m_data;
QHash<int, QHash<qint32, QVariant>> m_extraData;
QHash<int, QVector<QPair<qint32, quint64>>> m_attributeValues;
void computeExpandedLevels();
const PerfProfilerTraceManager *traceManager() const;