From 305a1a6ed18a15ac22863e16d836acff1ab42618 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 11 Sep 2023 08:53:42 +0200 Subject: [PATCH] CtfVisualizer: Fix computation of nesting level The computed nesting level (which row an event to show in) was solely based on begin+end events and "complete" events were ignored. Compute the rows afterwards, similar to the "parent" computation that the timeline model already does. Find the first row that is free, and use that for the row of the item. Change-Id: I890138c10f5038508da9b286b35d7bcfdf0ab64d Reviewed-by: Alessandro Portale Reviewed-by: Ulf Hermann --- src/libs/tracing/timelinemodel.cpp | 48 +++++++++++++++++++ src/libs/tracing/timelinemodel.h | 1 + .../ctfvisualizer/ctftimelinemodel.cpp | 18 ++----- src/plugins/ctfvisualizer/ctftimelinemodel.h | 2 +- .../timelinemodel/tst_timelinemodel.cpp | 13 +++++ 5 files changed, 68 insertions(+), 14 deletions(-) diff --git a/src/libs/tracing/timelinemodel.cpp b/src/libs/tracing/timelinemodel.cpp index d0c88f55280..46ab37f3f5a 100644 --- a/src/libs/tracing/timelinemodel.cpp +++ b/src/libs/tracing/timelinemodel.cpp @@ -83,6 +83,54 @@ void TimelineModel::computeNesting() } } +/*! + Compute all ranges' nesting level. Sort them into rows by finding the + first row that has "an open spot". +*/ +QList TimelineModel::computeRows(int *maxlevel) const +{ + *maxlevel = 0; + std::list rows; + QList levels; + levels.reserve(d->ranges.count()); + for (int range = 0; range != count(); ++range) { + TimelineModelPrivate::Range ¤t = d->ranges[range]; + // find first row for inserting + int level = 0; + auto rowIt = rows.begin(); + forever { + if (rowIt == rows.end()) { + // didn't find a row, insert new one + rows.push_back(range); + break; + } + TimelineModelPrivate::Range &rowItem = d->ranges[*rowIt]; + if (rowItem.start + rowItem.duration < current.start) { + // We've completely passed the item + // Use this row for the range + *rowIt = range; + break; + } + ++rowIt; + ++level; + } + levels.append(level); + if (level > *maxlevel) + *maxlevel = level; + // remove other rows that we passed + while (rowIt != rows.end()) { + TimelineModelPrivate::Range &rowItem = d->ranges[*rowIt]; + if (rowItem.start + rowItem.duration < current.start) { + // We've completely passed the item, remove + rowIt = rows.erase(rowIt); + } else { + ++rowIt; + } + } + } + return levels; +} + int TimelineModel::collapsedRowCount() const { return d->collapsedRowCount; diff --git a/src/libs/tracing/timelinemodel.h b/src/libs/tracing/timelinemodel.h index dd89fb0c5f4..5720909d563 100644 --- a/src/libs/tracing/timelinemodel.h +++ b/src/libs/tracing/timelinemodel.h @@ -133,6 +133,7 @@ protected: int insertStart(qint64 startTime, int selectionId); void insertEnd(int index, qint64 duration); void computeNesting(); + QList computeRows(int *maxlevel) const; void setCollapsedRowCount(int rows); void setExpandedRowCount(int rows); diff --git a/src/plugins/ctfvisualizer/ctftimelinemodel.cpp b/src/plugins/ctfvisualizer/ctftimelinemodel.cpp index 2655a86c065..f558e3599f9 100644 --- a/src/plugins/ctfvisualizer/ctftimelinemodel.cpp +++ b/src/plugins/ctfvisualizer/ctftimelinemodel.cpp @@ -105,7 +105,7 @@ int CtfTimelineModel::expandedRow(int index) const if (counterIdx > 0) { return m_counterIndexToRow[counterIdx - 1] + 1; } - return m_nestingLevels.value(index) + m_counterData.size() + 1; + return m_rows.value(index) + m_counterData.size() + 1; } int CtfTimelineModel::collapsedRow(int index) const @@ -187,6 +187,8 @@ void CtfTimelineModel::finalize(double traceBegin, double traceEnd, const QStrin m_details[index].insert(6, {reuse(Tr::tr("Unfinished")), reuse(Tr::tr("true"))}); } computeNesting(); + m_rows = computeRows(&m_maxStackSize); + ++m_maxStackSize; // index -> count QVector sortedCounterNames = m_counterNames; std::sort(sortedCounterNames.begin(), sortedCounterNames.end()); @@ -233,8 +235,6 @@ qint64 CtfTimelineModel::newStackEvent(const json &event, qint64 normalizedTime, const std::string &eventPhase, const std::string &name, int selectionId) { - int nestingLevel = m_openEventIds.size(); - m_maxStackSize = std::max(qsizetype(m_maxStackSize), qsizetype(m_openEventIds.size() + 1)); int index = 0; qint64 duration = -1; if (eventPhase == CtfEventTypeBegin) { @@ -250,29 +250,21 @@ qint64 CtfTimelineModel::newStackEvent(const json &event, qint64 normalizedTime, duration = qint64(event[CtfDurationKey]) * 1000; index = insert(normalizedTime, duration, selectionId); for (int i = m_openEventIds.size() - 1; i >= 0; --i) { - if (m_openEventIds[i] >= index) { + if (m_openEventIds[i] >= index) ++m_openEventIds[i]; - // if the event is before an open event, the nesting level decreases: - --nestingLevel; - } } } else { index = insert(normalizedTime, 0, selectionId); for (int i = m_openEventIds.size() - 1; i >= 0; --i) { - if (m_openEventIds[i] >= index) { + if (m_openEventIds[i] >= index) ++m_openEventIds[i]; - --nestingLevel; - } } } if (index >= m_details.size()) { m_details.resize(index + 1); m_details[index] = QMap>(); - m_nestingLevels.resize(index + 1); - m_nestingLevels[index] = nestingLevel; } else { m_details.insert(index, QMap>()); - m_nestingLevels.insert(index, nestingLevel); } if (m_counterValues.size() > index) { // if the event was inserted before any counter, we need diff --git a/src/plugins/ctfvisualizer/ctftimelinemodel.h b/src/plugins/ctfvisualizer/ctftimelinemodel.h index 186a0dcefeb..fe7d8c4c0ad 100644 --- a/src/plugins/ctfvisualizer/ctftimelinemodel.h +++ b/src/plugins/ctfvisualizer/ctftimelinemodel.h @@ -73,7 +73,7 @@ protected: QString m_processName; int m_maxStackSize = 0; - QVector m_nestingLevels; + QVector m_rows; QVector>> m_details; QSet m_handledTypeIds; QStack m_openEventIds; diff --git a/tests/auto/tracing/timelinemodel/tst_timelinemodel.cpp b/tests/auto/tracing/timelinemodel/tst_timelinemodel.cpp index 559b827de2e..72f16510bce 100644 --- a/tests/auto/tracing/timelinemodel/tst_timelinemodel.cpp +++ b/tests/auto/tracing/timelinemodel/tst_timelinemodel.cpp @@ -57,6 +57,7 @@ private slots: void rowCount(); void prevNext(); void parentingOfEqualStarts(); + void rows(); private: TimelineModelAggregator aggregator; @@ -463,6 +464,18 @@ void tst_TimelineModel::parentingOfEqualStarts() QCOMPARE(dummy.lastIndex(2), 1); } +void tst_TimelineModel::rows() +{ + DummyModel dummy(&aggregator); + dummy.loadData(); + int maxlevel; + const QList levels = dummy.computeRows(&maxlevel); + QCOMPARE(levels.at(0), 0); + QCOMPARE(levels.at(7), 7); + QCOMPARE(levels.at(10), 2); + QCOMPARE(maxlevel, 15); +} + QTEST_GUILESS_MAIN(tst_TimelineModel) #include "tst_timelinemodel.moc"