From: Milian Wolff Date: Sun, 6 Sep 2015 17:37:40 +0000 (+0200) Subject: Use the TopDownData as input to generate the FlameGraph. X-Git-Tag: submit/tizen/20180620.112952^2~286 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=30b079ccb3bd670ee145fa8d79ab8d7e476e5c4f;p=sdk%2Ftools%2Fheaptrack.git Use the TopDownData as input to generate the FlameGraph. --- diff --git a/gui/flamegraph.cpp b/gui/flamegraph.cpp index bf4ba75..e715ec8 100644 --- a/gui/flamegraph.cpp +++ b/gui/flamegraph.cpp @@ -49,6 +49,16 @@ quint64 FrameGraphicsItem::cost() const return m_cost; } +void FrameGraphicsItem::setCost(quint64 cost) +{ + m_cost = cost; +} + +QString FrameGraphicsItem::function() const +{ + return m_function; +} + void FrameGraphicsItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* /*widget*/) { if (isSelected() || m_isHovered) { @@ -107,13 +117,6 @@ void FrameGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) namespace { -struct Frame { - quint64 cost = 0; - using Stack = QMap; - Stack children; -}; -using Stack = Frame::Stack; - /** * Generate a color from the "mem" color space used in upstream FlameGraph.pl */ @@ -145,41 +148,32 @@ void layoutItems(FrameGraphicsItem *parent) } } -/** - * Convert the top-down graph into a tree of FrameGraphicsItem. - */ -void toGraphicsItems(const Stack& data, FrameGraphicsItem *parent) +FrameGraphicsItem* findItemByFunction(const QList& items, const QString& function) { - for (auto it = data.constBegin(); it != data.constEnd(); ++it) { - FrameGraphicsItem* item = new FrameGraphicsItem(it.value().cost, it.key(), parent); - item->setPen(parent->pen()); - item->setBrush(color()); - toGraphicsItems(it.value().children, item); + foreach (auto item_, items) { + auto item = static_cast(item_); + if (item->function() == function) { + return item; + } } + return nullptr; } /** - * Build a top-down graph from the bottom-up data in @p mergedAllocations + * Convert the top-down graph into a tree of FrameGraphicsItem. */ -void buildFlameGraph(const QVector& mergedAllocations, Stack* topStack) +void toGraphicsItems(const QVector& data, FrameGraphicsItem *parent) { - foreach (const auto& row, mergedAllocations) { - if (row.children.isEmpty()) { - // leaf node found, bubble up the parent chain to build a top-down tree - auto node = &row; - auto stack = topStack; - while (node) { - auto& data = (*stack)[node->location.function]; - // always use the leaf node's cost and propagate that one up the chain - // otherwise we'd count the cost of some nodes multiple times - data.cost += row.allocations; - stack = &data.children; - node = node->parent; - } + foreach (const auto& row, data) { + auto item = findItemByFunction(parent->childItems(), row.location.function); + if (!item) { + item = new FrameGraphicsItem(row.allocations, row.location.function, parent); + item->setPen(parent->pen()); + item->setBrush(color()); } else { - // recurse to find a leaf - buildFlameGraph(row.children, topStack); + item->setCost(item->cost() + row.allocations); } + toGraphicsItems(row.children, item); } } @@ -235,23 +229,20 @@ void FlameGraph::setData(FrameGraphicsItem* rootItem) } } -FrameGraphicsItem* FlameGraph::parseData(const QVector& data) +FrameGraphicsItem* FlameGraph::parseData(const QVector& topDownData) { - Stack stack; - buildFlameGraph(data, &stack); - double totalCost = 0; - foreach(const auto& frame, stack) { - totalCost += frame.cost; + foreach(const auto& frame, topDownData) { + totalCost += frame.allocations; } KColorScheme scheme(QPalette::Active); const QPen pen(scheme.foreground().color()); - auto rootItem = new FrameGraphicsItem(totalCost, i18n("total allocations")); + auto rootItem = new FrameGraphicsItem(totalCost, i18n("%1 allocations in total", totalCost)); rootItem->setBrush(scheme.background()); rootItem->setPen(pen); - toGraphicsItems(stack, rootItem); + toGraphicsItems(topDownData, rootItem); return rootItem; } diff --git a/gui/flamegraph.h b/gui/flamegraph.h index 291c5ba..994f52b 100644 --- a/gui/flamegraph.h +++ b/gui/flamegraph.h @@ -33,6 +33,8 @@ public: FrameGraphicsItem(const quint64 cost, const QString& function, FrameGraphicsItem* parent = nullptr); quint64 cost() const; + void setCost(quint64 cost); + QString function() const; void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = nullptr) override; @@ -56,7 +58,7 @@ public: void setData(FrameGraphicsItem* rootFrame); // called from background thread - static FrameGraphicsItem* parseData(const QVector& data); + static FrameGraphicsItem* parseData(const QVector& topDownData); protected: bool eventFilter(QObject* object, QEvent* event) override; diff --git a/gui/parser.cpp b/gui/parser.cpp index 228918c..36993c8 100644 --- a/gui/parser.cpp +++ b/gui/parser.cpp @@ -246,7 +246,7 @@ void Parser::parse(const QString& path) emit chartDataAvailable(data.chartData); const auto topDownData = toTopDownData(mergedAllocations); emit topDownDataAvailable(topDownData); - emit flameGraphDataAvailable(FlameGraph::parseData(mergedAllocations)); + emit flameGraphDataAvailable(FlameGraph::parseData(topDownData)); emit finished(); }); }