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
|
||||
};
|
||||
|
||||
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)
|
||||
|
@@ -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));
|
||||
|
||||
|
@@ -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;
|
||||
});
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user