Build flame graph on demand.
authorMilian Wolff <mail@milianw.de>
Sat, 5 Dec 2015 00:50:39 +0000 (01:50 +0100)
committerMilian Wolff <mail@milianw.de>
Sat, 5 Dec 2015 00:50:39 +0000 (01:50 +0100)
Reduces memory consumption when the flame graph is not being displayed.

gui/flamegraph.cpp
gui/flamegraph.h
gui/mainwindow.cpp
gui/parser.cpp
gui/parser.h

index 5c91d8c..4777475 100644 (file)
@@ -25,7 +25,7 @@
 #include <QGraphicsScene>
 #include <QStyleOption>
 #include <QGraphicsView>
-#include <QGraphicsItem>
+#include <QGraphicsRectItem>
 #include <QWheelEvent>
 #include <QEvent>
 #include <QToolTip>
 #include <KLocalizedString>
 #include <KColorScheme>
 
+class FrameGraphicsItem : public QGraphicsRectItem
+{
+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;
+
+protected:
+    void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
+    void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
+    void showToolTip() const;
+
+private:
+    quint64 m_cost;
+    QString m_function;
+    bool m_isHovered;
+};
+
 FrameGraphicsItem::FrameGraphicsItem(const quint64 cost, const QString& function, FrameGraphicsItem* parent)
     : QGraphicsRectItem(parent)
     , m_cost(cost)
@@ -185,6 +207,23 @@ void toGraphicsItems(const QVector<RowData>& data, FrameGraphicsItem *parent)
     }
 }
 
+FrameGraphicsItem* parseData(const QVector<RowData>& topDownData)
+{
+    double totalCost = 0;
+    foreach(const auto& frame, topDownData) {
+        totalCost += frame.allocations;
+    }
+
+    KColorScheme scheme(QPalette::Active);
+    const QPen pen(scheme.foreground().color());
+
+    auto rootItem = new FrameGraphicsItem(totalCost, i18n("%1 allocations in total", totalCost));
+    rootItem->setBrush(scheme.background());
+    rootItem->setPen(pen);
+    toGraphicsItems(topDownData, rootItem);
+    return rootItem;
+}
+
 }
 
 FlameGraph::FlameGraph(QWidget* parent, Qt::WindowFlags flags)
@@ -223,11 +262,35 @@ bool FlameGraph::eventFilter(QObject* object, QEvent* event)
     return ret;
 }
 
+void FlameGraph::showEvent(QShowEvent* event)
+{
+    setData(parseData(m_topDownData));
+    QWidget::showEvent(event);
+}
+
+void FlameGraph::hideEvent(QHideEvent* event)
+{
+    setData(nullptr);
+    QWidget::hideEvent(event);
+}
+
+void FlameGraph::setTopDownData(const TreeData& topDownData)
+{
+    m_topDownData = topDownData;
+    if (isVisible()) {
+        setData(parseData(topDownData));
+    }
+}
+
 void FlameGraph::setData(FrameGraphicsItem* rootItem)
 {
     m_scene->clear();
     m_rootItem = rootItem;
     m_selectedItem = rootItem;
+    if (!rootItem) {
+        return;
+    }
+
     // layouting needs a root item with a given height, the rest will be overwritten later
     rootItem->setRect(0, 0, 800, m_view->fontMetrics().height() + 4);
     m_scene->addItem(rootItem);
@@ -237,23 +300,6 @@ void FlameGraph::setData(FrameGraphicsItem* rootItem)
     }
 }
 
-FrameGraphicsItem* FlameGraph::parseData(const QVector<RowData>& topDownData)
-{
-    double totalCost = 0;
-    foreach(const auto& frame, topDownData) {
-        totalCost += frame.allocations;
-    }
-
-    KColorScheme scheme(QPalette::Active);
-    const QPen pen(scheme.foreground().color());
-
-    auto rootItem = new FrameGraphicsItem(totalCost, i18n("%1 allocations in total", totalCost));
-    rootItem->setBrush(scheme.background());
-    rootItem->setPen(pen);
-    toGraphicsItems(topDownData, rootItem);
-    return rootItem;
-}
-
 void FlameGraph::selectItem(FrameGraphicsItem* item)
 {
     if (!item) {
index 994f52b..4c00b0e 100644 (file)
 #define FLAMEGRAPH_H
 
 #include <QWidget>
-#include <QGraphicsRectItem>
 #include "treemodel.h"
 
 class QGraphicsScene;
 class QGraphicsView;
 
-class FrameGraphicsItem : public QGraphicsRectItem
-{
-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;
-
-protected:
-    void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
-    void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
-    void showToolTip() const;
-
-private:
-    quint64 m_cost;
-    QString m_function;
-    bool m_isHovered;
-};
+class FrameGraphicsItem;
 
 class FlameGraph : public QWidget
 {
@@ -56,16 +35,19 @@ public:
     FlameGraph(QWidget* parent = nullptr, Qt::WindowFlags flags = 0);
     ~FlameGraph();
 
-    void setData(FrameGraphicsItem* rootFrame);
-    // called from background thread
-    static FrameGraphicsItem* parseData(const QVector<RowData>& topDownData);
+    void setTopDownData(const TreeData& topDownData);
 
 protected:
     bool eventFilter(QObject* object, QEvent* event) override;
+    void showEvent(QShowEvent* event) override;
+    void hideEvent(QHideEvent* event) override;
 
 private:
+    void setData(FrameGraphicsItem* rootItem);
     void selectItem(FrameGraphicsItem* item);
 
+    TreeData m_topDownData;
+
     QGraphicsScene* m_scene;
     QGraphicsView* m_view;
     FrameGraphicsItem* m_rootItem;
index e50dd1a..08b441e 100644 (file)
@@ -68,8 +68,8 @@ MainWindow::MainWindow(QWidget* parent)
             allocationsModel, &ChartModel::resetData);
     connect(m_parser, &Parser::summaryAvailable,
             m_ui->summary, &QLabel::setText);
-    connect(m_parser, &Parser::flameGraphDataAvailable,
-            m_ui->flameGraphTab, &FlameGraph::setData);
+    connect(m_parser, &Parser::topDownDataAvailable,
+            m_ui->flameGraphTab, &FlameGraph::setTopDownData);
     connect(m_parser, &Parser::finished,
             this, [&] { m_ui->pages->setCurrentWidget(m_ui->resultsPage); });
 
index 37b52e3..bfbc2d3 100644 (file)
@@ -27,7 +27,6 @@
 #include <QDebug>
 
 #include "../accumulatedtracedata.h"
-#include "flamegraph.h"
 
 #include <vector>
 #include <memory>
@@ -396,8 +395,6 @@ void Parser::parse(const QString& path)
             emit bottomUpDataAvailable(mergedAllocations);
             const auto topDownData = toTopDownData(mergedAllocations);
             emit topDownDataAvailable(topDownData);
-            // TODO: do this on-demand when the flame graph is shown for the first time
-            emit flameGraphDataAvailable(FlameGraph::parseData(topDownData));
         }) << make_job([this, data, stdPath]() {
             // this mutates data, and thus anything running in parallel must
             // not access data
index 46b1755..7a57772 100644 (file)
@@ -25,8 +25,6 @@
 #include "treemodel.h"
 #include "chartmodel.h"
 
-class FrameGraphicsItem;
-
 class Parser : public QObject
 {
     Q_OBJECT
@@ -44,7 +42,6 @@ signals:
     void consumedChartDataAvailable(const ChartData& data);
     void allocationsChartDataAvailable(const ChartData& data);
     void allocatedChartDataAvailable(const ChartData& data);
-    void flameGraphDataAvailable(FrameGraphicsItem* rootItem);
     void finished();
 };