Skip to content

Commit

Permalink
allow timeline filtering in diff view
Browse files Browse the repository at this point in the history
  • Loading branch information
lievenhey committed Oct 6, 2021
1 parent 3ddf05b commit 1dc1b2d
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 30 deletions.
113 changes: 97 additions & 16 deletions src/diffviewwidget.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
#include "diffviewwidget.h"

#include <QAction>
#include <QLabel>
#include <QMenu>
#include <QProgressBar>

#include <kddockwidgets/DockWidget.h>
#include <kddockwidgets/MainWindow.h>

#include "dockwidgetsetup.h"
#include "filterandzoomstack.h"
#include "models/treemodel.h"
#include "parsers/perf/perfparser.h"
#include "resultsutil.h"
#include "settings.h"
#include "timelinewidget.h"

#include "ui_resultsdiffpage.h"

Expand All @@ -11,44 +23,113 @@ DiffViewWidget::DiffViewWidget(QWidget* parent)
, ui(new Ui::ResultsDiffPage)
, m_parserA(new PerfParser(this))
, m_parserB(new PerfParser(this))
, m_filterAndZoomStackA(new FilterAndZoomStack(this))
, m_filterAndZoomStackB(new FilterAndZoomStack(this))
, m_filterMenu(new QMenu(this))
, m_model(new DiffViewModel(this))
, m_contents(createDockingArea(QStringLiteral("diffview"), this))
, m_timelineA(new TimeLineWidget(m_parserA, m_filterMenu, m_filterAndZoomStackA, this))
, m_timelineB(new TimeLineWidget(m_parserB, m_filterMenu, m_filterAndZoomStackB, this))
{
ui->setupUi(this);

ui->diffTreeView->setModel(m_model);
ui->bottomUpVerticalLayout->addWidget(m_contents);

ResultsUtil::setupTreeView(ui->diffTreeView, ui->diffSearch, m_model);
ResultsUtil::setupCostDelegate<DiffViewModel>(m_model, ui->diffTreeView);

auto dockify = [](QWidget* widget, const QString& id, const QString& title, const QString& shortcut) {
auto* dock = new KDDockWidgets::DockWidget(id);
dock->setWidget(widget);
dock->setTitle(title);
dock->toggleAction()->setShortcut(shortcut);
return dock;
};

m_timelineDockA = dockify(m_timelineA, QStringLiteral("timelinea"), tr("Timeline A"), tr("Ctrl+A"));
m_contents->addDockWidget(m_timelineDockA, KDDockWidgets::Location_OnBottom);
m_timelineDockB = dockify(m_timelineB, QStringLiteral("timelineb"), tr("Timeline B"), tr("Ctrl+B"));
m_timelineDockA->addDockWidgetAsTab(m_timelineDockB);

auto repositionFilterBusyIndicator = [this] {
auto geometry = m_filterBusyIndicator->geometry();
geometry.setWidth(width() / 2);
geometry.moveCenter(rect().center());
m_filterBusyIndicator->setGeometry(geometry);
};

connect(m_parserA, &PerfParser::parsingStarted, this, [this, repositionFilterBusyIndicator] {
repositionFilterBusyIndicator();
m_filterBusyIndicator->setVisible(true);
});

connect(m_parserB, &PerfParser::parsingStarted, this, [this, repositionFilterBusyIndicator] {
repositionFilterBusyIndicator();
m_filterBusyIndicator->setVisible(true);
});

connect(m_parserA, &PerfParser::parsingFinished, this, [this] {
m_aFinished = true;
if (m_bFinished) {
viewData();
m_filterBusyIndicator->setVisible(false);
}
});

connect(m_parserB, &PerfParser::parsingFinished, this, [this] {
m_bFinished = true;
if (m_aFinished) {
viewData();
m_filterBusyIndicator->setVisible(false);
}
});

connect(m_parserA, &PerfParser::bottomUpDataAvailable, this, [this](const Data::BottomUpResults& results) {
m_resultsA = results;

const auto data = Data::DiffViewResults::fromBottomUp(m_resultsA, m_resultsB);

m_model->setData(data);
});

connect(m_parserB, &PerfParser::bottomUpDataAvailable, this, [this](const Data::BottomUpResults& results) {
m_resultsB = results;

const auto data = Data::DiffViewResults::fromBottomUp(m_resultsA, m_resultsB);

m_model->setData(data);
});

connect(m_filterAndZoomStackA, &FilterAndZoomStack::filterChanged, this, [this](const Data::FilterAction& action) {
m_bFinished = true;
m_parserA->filterResults(action);
});
connect(m_filterAndZoomStackB, &FilterAndZoomStack::filterChanged, this, [this](const Data::FilterAction& action) {
m_aFinished = true;
m_parserB->filterResults(action);
});

{
m_filterBusyIndicator = new QWidget(this);
m_filterBusyIndicator->setMinimumHeight(100);
m_filterBusyIndicator->setVisible(false);
m_filterBusyIndicator->setToolTip(tr("Filtering in progress, please wait..."));
auto layout = new QVBoxLayout(m_filterBusyIndicator);
layout->setAlignment(Qt::AlignCenter);
auto progressBar = new QProgressBar(m_filterBusyIndicator);
layout->addWidget(progressBar);
progressBar->setMaximum(0);
auto label = new QLabel(m_filterBusyIndicator->toolTip(), m_filterBusyIndicator);
label->setAlignment(Qt::AlignCenter);
layout->addWidget(label);
}
}

DiffViewWidget::~DiffViewWidget() = default;

void DiffViewWidget::open(const QString& a, const QString& b)
{
m_parserA->startParseFile(a, {}, {}, {}, {}, {}, {});
m_parserB->startParseFile(b, {}, {}, {}, {}, {}, {});
}

void DiffViewWidget::viewData()
{
m_aFinished = false;
m_bFinished = false;

const auto data =
Data::DiffViewResults::fromTopDown(Data::TopDownResults::fromBottomUp(m_parserA->bottomUpResults()),
Data::TopDownResults::fromBottomUp(m_parserB->bottomUpResults()));
m_model->setData(data);
auto settings = Settings::instance();
m_parserA->startParseFile(a, settings->sysroot(), settings->kallsyms(), settings->debugPaths(),
settings->extraLibPaths(), settings->appPath(), settings->arch());
m_parserB->startParseFile(b, settings->sysroot(), settings->kallsyms(), settings->debugPaths(),
settings->extraLibPaths(), settings->appPath(), settings->arch());
}
23 changes: 20 additions & 3 deletions src/diffviewwidget.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
#ifndef DIFFVIEWWIDGET_H
#define DIFFVIEWWIDGET_H

#include "data.h"
#include <QWidget>

class QMenu;
class PerfParser;
class DiffViewModel;
class TimeLineWidget;
class FilterAndZoomStack;

namespace KDDockWidgets {
class MainWindow;
class DockWidget;
}

namespace Ui {
class ResultsDiffPage;
Expand All @@ -20,14 +29,22 @@ class DiffViewWidget : public QWidget
public slots:
void open(const QString& a, const QString& b);

private slots:
void viewData();

private:
QScopedPointer<Ui::ResultsDiffPage> ui;
PerfParser* m_parserA;
PerfParser* m_parserB;
FilterAndZoomStack* m_filterAndZoomStackA;
FilterAndZoomStack* m_filterAndZoomStackB;
QMenu* m_filterMenu;
DiffViewModel* m_model;
KDDockWidgets::MainWindow* m_contents;
KDDockWidgets::DockWidget* m_timelineDockA;
KDDockWidgets::DockWidget* m_timelineDockB;
TimeLineWidget* m_timelineA;
TimeLineWidget* m_timelineB;
QWidget* m_filterBusyIndicator = nullptr;
Data::BottomUpResults m_resultsA;
Data::BottomUpResults m_resultsB;

bool m_aFinished = false;
bool m_bFinished = false;
Expand Down
19 changes: 9 additions & 10 deletions src/models/data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -354,10 +354,10 @@ const Data::ThreadEvents* Data::EventResults::findThread(qint32 pid, qint32 tid)
return const_cast<Data::EventResults*>(this)->findThread(pid, tid);
}

DiffViewResults DiffViewResults::fromTopDown(const TopDownResults& a, const TopDownResults& b)
DiffViewResults DiffViewResults::fromBottomUp(const Data::BottomUpResults& a, const Data::BottomUpResults& b)
{
DiffViewResults results;
results.costs.initializeCostsFrom(a.inclusiveCosts);
results.costs.initializeCostsFrom(a.costs);
results.costs.setTotalCosts(QVector<qint64>(results.costs.numTypes(), 1'000'000));

// compare two symbols
Expand All @@ -368,7 +368,7 @@ DiffViewResults DiffViewResults::fromTopDown(const TopDownResults& a, const TopD
return (a.symbol == b.symbol && a.binary == b.binary);
};

auto findSibling = [cmpSymbols](const QVector<TopDown>& children, const Symbol& symbol) -> const TopDown* {
auto findSibling = [cmpSymbols](const QVector<BottomUp>& children, const Symbol& symbol) -> const BottomUp* {
for (const auto& child : children) {
if (cmpSymbols(symbol, child.symbol)) {
return &child;
Expand All @@ -378,9 +378,9 @@ DiffViewResults DiffViewResults::fromTopDown(const TopDownResults& a, const TopD
};

int id = 0;
std::function<void(DiffView*, const QVector<TopDown>&, const QVector<TopDown>&)> walkTree =
[&walkTree, findSibling, &results, &id, a, b](DiffView* currentNode, const QVector<TopDown>& aChildren,
const QVector<TopDown>& bChildren) {
std::function<void(DiffView*, const QVector<BottomUp>&, const QVector<BottomUp>&)> walkTree =
[&walkTree, findSibling, &results, &id, a, b](DiffView* currentNode, const QVector<BottomUp>& aChildren,
const QVector<BottomUp>& bChildren) {
for (const auto& node : aChildren) {
auto sibling = findSibling(bChildren, node.symbol);

Expand All @@ -391,10 +391,9 @@ DiffViewResults DiffViewResults::fromTopDown(const TopDownResults& a, const TopD
diff.parent = currentNode;
diff.id = id;

for (int i = 0; i < a.inclusiveCosts.numTypes(); i++) {
const auto diff = static_cast<double>(b.inclusiveCosts.cost(i, node.id)
- a.inclusiveCosts.cost(i, sibling->id))
/ (b.inclusiveCosts.totalCost(i) - a.inclusiveCosts.totalCost(i));
for (int i = 0; i < a.costs.numTypes(); i++) {
const auto diff = static_cast<double>(b.costs.cost(i, node.id) - a.costs.cost(i, sibling->id))
/ (b.costs.totalCost(i) - a.costs.totalCost(i));
results.costs.add(i, id, diff * 1'000'000);
}

Expand Down
2 changes: 1 addition & 1 deletion src/models/data.h
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ struct DiffViewResults
DiffView root;
Costs costs;

static DiffViewResults fromTopDown(const Data::TopDownResults& a, const Data::TopDownResults& b);
static DiffViewResults fromBottomUp(const Data::BottomUpResults& a, const Data::BottomUpResults& b);
};

using SymbolCostMap = QHash<Symbol, ItemCost>;
Expand Down

0 comments on commit 1dc1b2d

Please sign in to comment.