Skip to content

Commit

Permalink
glue diffing on perfparser
Browse files Browse the repository at this point in the history
  • Loading branch information
lievenhey committed Dec 3, 2021
1 parent 0a3aabf commit d0b37e5
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 71 deletions.
19 changes: 17 additions & 2 deletions src/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,21 @@ MainWindow::MainWindow(QWidget* parent)
connect(m_startPage, &StartPage::recordButtonClicked, this, &MainWindow::onRecordButtonClicked);
connect(m_startPage, &StartPage::stopParseButtonClicked, this,
static_cast<void (MainWindow::*)()>(&MainWindow::clear));
connect(m_startPage, &StartPage::diffButtonClicked, this, [this] {
const auto fileNameA = QFileDialog::getOpenFileName(this, tr("Open File A"), QDir::currentPath(),
tr("Data Files (perf*.data perf.data.*);;All Files (*)"));
if (fileNameA.isEmpty()) {
return;
}

const auto fileNameB = QFileDialog::getOpenFileName(this, tr("Open File B"), QDir::currentPath(),
tr("Data Files (perf*.data perf.data.*);;All Files (*)"));
if (fileNameB.isEmpty()) {
return;
}

openFile(fileNameA, false, fileNameB);
});
connect(m_parser, &PerfParser::progress, m_startPage, &StartPage::onParseFileProgress);
connect(this, &MainWindow::openFileError, m_startPage, &StartPage::onOpenFileError);
connect(m_recordPage, &RecordPage::homeButtonClicked, this, &MainWindow::onHomeButtonClicked);
Expand Down Expand Up @@ -363,7 +378,7 @@ void MainWindow::clear()
clear(false);
}

void MainWindow::openFile(const QString& path, bool isReload)
void MainWindow::openFile(const QString& path, bool isReload, const QString& diffFile)
{
clear(isReload);

Expand All @@ -374,7 +389,7 @@ void MainWindow::openFile(const QString& path, bool isReload)
m_pageStack->setCurrentWidget(m_startPage);

// TODO: support input files of different types via plugins
m_parser->startParseFile(path);
m_parser->startParseFile(path, diffFile);
m_reloadAction->setData(path);
m_exportAction->setData(QUrl::fromLocalFile(file.absoluteFilePath() + QLatin1String(".perfparser")));

Expand Down
2 changes: 1 addition & 1 deletion src/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public slots:

private:
void clear(bool isReload);
void openFile(const QString& path, bool isReload);
void openFile(const QString& path, bool isReload, const QString& diffFile = QStringLiteral(""));
void closeEvent(QCloseEvent* event) override;
void setupCodeNavigationMenu();

Expand Down
40 changes: 40 additions & 0 deletions src/models/data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,26 @@ void buildPerLibrary(const TopDown* node, PerLibraryResults& results, QHash<QStr
buildPerLibrary(&child, results, binaryToResultIndex, costs);
}
}

void diffBottomUpResults(const BottomUp& a, const BottomUp* b, BottomUp* result_node, const Costs& costs_a,
const Costs& costs_b, Costs* costs_result)
{
for (const auto& node : a.children) {
const auto sibling = b->entryForSymbol(node.symbol);
if (sibling) {
BottomUp diffed;
diffed.id = node.id;
diffed.symbol = node.symbol;

for (int i = 0; i < costs_result->numTypes(); i += 2) {
costs_result->add(i, diffed.id, costs_a.cost(i, node.id) - costs_b.cost(i, sibling->id));
}

result_node->children.push_back(diffed);
diffBottomUpResults(node, sibling, &result_node->children.back(), costs_a, costs_b, costs_result);
}
}
}
}

QString Data::prettifySymbol(const QString& name)
Expand Down Expand Up @@ -389,3 +409,23 @@ const Data::ThreadEvents* Data::EventResults::findThread(qint32 pid, qint32 tid)
{
return const_cast<Data::EventResults*>(this)->findThread(pid, tid);
}

BottomUpResults BottomUpResults::diffBottomUpResults(const BottomUpResults& a, const BottomUpResults& b)
{
if (a.costs.numTypes() != b.costs.numTypes()) {
return {};
}

BottomUpResults results;

for (int i = 0; i < a.costs.numTypes(); i++) {
results.costs.addType(i, a.costs.typeName(i), a.costs.unit(i));
results.costs.addTotalCost(i , a.costs.totalCost(i) - b.costs.totalCost(i));
}

::diffBottomUpResults(a.root, &b.root, &results.root, a.costs, b.costs, &results.costs);

Data::BottomUp::initializeParents(&results.root);

return results;
}
2 changes: 2 additions & 0 deletions src/models/data.h
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,8 @@ struct BottomUpResults
return parent;
}

static BottomUpResults diffBottomUpResults(const Data::BottomUpResults& a, const Data::BottomUpResults& b);

private:
quint32 maxBottomUpId = 0;

Expand Down
147 changes: 97 additions & 50 deletions src/parsers/perf/perfparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1332,7 +1332,7 @@ PerfParser::PerfParser(QObject* parent)

PerfParser::~PerfParser() = default;

void PerfParser::startParseFile(const QString& path)
void PerfParser::startParseFile(const QString& path, const QString& diffFile)
{
Q_ASSERT(!m_isParsing);

Expand All @@ -1358,6 +1358,7 @@ void PerfParser::startParseFile(const QString& path)

auto parserArgs = [this](const QString& filename) {
const auto settings = Settings::instance();

QStringList parserArgs = {QStringLiteral("--input"), decompressIfNeeded(filename),
QStringLiteral("--max-frames"), QStringLiteral("1024")};
const auto sysroot = settings->sysroot();
Expand Down Expand Up @@ -1405,7 +1406,7 @@ void PerfParser::startParseFile(const QString& path)

emit parsingStarted();
using namespace ThreadWeaver;
stream() << make_job([path, parserBinary, parserArgs, env, this]() {
stream() << make_job([path, parserBinary, env, this]() {
PerfParserPrivate d;
connect(&d, &PerfParserPrivate::progress, this, &PerfParser::progress);
connect(this, &PerfParser::stopRequested, &d, &PerfParserPrivate::stop);
Expand Down Expand Up @@ -1451,55 +1452,55 @@ void PerfParser::startParseFile(const QString& path)

d.setInput(&process);

const auto exitCodeHandler = [finalize, this](int exitCode, QProcess::ExitStatus exitStatus) {
if (m_stopRequested) {
emit parsingFailed(tr("Parsing stopped."));
return;
}
qCDebug(LOG_PERFPARSER) << exitCode << exitStatus;

enum ErrorCodes
{
NoError,
TcpSocketError,
CannotOpen,
BadMagic,
HeaderError,
DataError,
MissingData,
InvalidOption
};
switch (exitCode) {
case NoError:
finalize();
break;
case TcpSocketError:
emit parsingFailed(
tr("The hotspot-perfparser binary exited with code %1 (TCP socket error).").arg(exitCode));
break;
case CannotOpen:
emit parsingFailed(
tr("The hotspot-perfparser binary exited with code %1 (file could not be opened).").arg(exitCode));
break;
case BadMagic:
case HeaderError:
case DataError:
case MissingData:
emit parsingFailed(
tr("The hotspot-perfparser binary exited with code %1 (invalid perf data file).").arg(exitCode));
break;
case InvalidOption:
emit parsingFailed(
tr("The hotspot-perfparser binary exited with code %1 (invalid option).").arg(exitCode));
break;
default:
emit parsingFailed(tr("The hotspot-perfparser binary exited with code %1.").arg(exitCode));
break;
}
};

connect(&process, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), &process,
[finalize, this](int exitCode, QProcess::ExitStatus exitStatus) {
if (m_stopRequested) {
emit parsingFailed(tr("Parsing stopped."));
return;
}
qCDebug(LOG_PERFPARSER) << exitCode << exitStatus;

enum ErrorCodes
{
NoError,
TcpSocketError,
CannotOpen,
BadMagic,
HeaderError,
DataError,
MissingData,
InvalidOption
};
switch (exitCode) {
case NoError:
finalize();
break;
case TcpSocketError:
emit parsingFailed(
tr("The hotspot-perfparser binary exited with code %1 (TCP socket error).").arg(exitCode));
break;
case CannotOpen:
emit parsingFailed(
tr("The hotspot-perfparser binary exited with code %1 (file could not be opened).")
.arg(exitCode));
break;
case BadMagic:
case HeaderError:
case DataError:
case MissingData:
emit parsingFailed(
tr("The hotspot-perfparser binary exited with code %1 (invalid perf data file).")
.arg(exitCode));
break;
case InvalidOption:
emit parsingFailed(
tr("The hotspot-perfparser binary exited with code %1 (invalid option).").arg(exitCode));
break;
default:
emit parsingFailed(tr("The hotspot-perfparser binary exited with code %1.").arg(exitCode));
break;
}
});
exitCodeHandler);

connect(&process, &QProcess::errorOccurred, &process, [&d, &process, this](QProcess::ProcessError error) {
if (m_stopRequested) {
Expand All @@ -1523,6 +1524,52 @@ void PerfParser::startParseFile(const QString& path)
&QEventLoop::quit);
loop.exec();
});

if (diffFile.isEmpty()) {
return;
}

PerfParser otherData;

otherData.startParseFile(diffFile);
QEventLoop loop;
connect(&otherData, &PerfParser::parsingFinished, &loop, &QEventLoop::quit);
connect(&otherData, &PerfParser::parsingFailed, &loop, &QEventLoop::quit);
connect(&otherData, &PerfParser::parsingFailed, this, [this](const QString& error) { emit parsingFailed(error); });

connect(&otherData, &PerfParser::bottomUpDataAvailable, &otherData,
[this, &otherData](const Data::BottomUpResults& otherResults) {
if (m_bottomUpResults.root.children.size() > 0) {
this->m_callerCalleeResults = {};

const auto diffResults =
Data::BottomUpResults::mergeBottomUpResults(m_bottomUpResults, otherResults);
m_bottomUpResults = diffResults;
const auto topDown = Data::TopDownResults::fromBottomUp(diffResults);
Data::CallerCalleeResults callerCalleeResults;
Data::callerCalleesFromBottomUpData(diffResults, &callerCalleeResults);
emit bottomUpDataAvailable(diffResults);
emit topDownDataAvailable(Data::TopDownResults::fromBottomUp(diffResults));
emit callerCalleeDataAvailable(callerCalleeResults);
} else {
connect(this, &PerfParser::bottomUpDataAvailable, &otherData,
[this, &otherData, otherResults](const Data::BottomUpResults& results) {
this->m_bottomUpResults = {};
this->m_callerCalleeResults = {};

const auto diffResults =
Data::BottomUpResults::mergeBottomUpResults(results, otherResults);
const auto topDown = Data::TopDownResults::fromBottomUp(diffResults);
Data::CallerCalleeResults callerCalleeResults;
Data::callerCalleesFromBottomUpData(diffResults, &callerCalleeResults);
emit bottomUpDataAvailable(diffResults);
emit topDownDataAvailable(Data::TopDownResults::fromBottomUp(diffResults));
emit callerCalleeDataAvailable(callerCalleeResults);
});
}
});

loop.exec();
}

void PerfParser::filterResults(const Data::FilterAction& filter)
Expand Down
5 changes: 4 additions & 1 deletion src/parsers/perf/perfparser.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class PerfParser : public QObject
explicit PerfParser(QObject* parent = nullptr);
~PerfParser();

void startParseFile(const QString& path);
void startParseFile(const QString& path, const QString& diffFile = QStringLiteral(""));

void filterResults(const Data::FilterAction& filter);

Expand All @@ -69,10 +69,13 @@ class PerfParser : public QObject
void parsingStarted();
void summaryDataAvailable(const Data::Summary& data);
void bottomUpDataAvailable(const Data::BottomUpResults& data);
void firstBottomUpDataAvailable(const Data::BottomUpResults& data);
void secondBottomUpDataAvailable(const Data::BottomUpResults& data);
void topDownDataAvailable(const Data::TopDownResults& data);
void perLibraryDataAvailable(const Data::PerLibraryResults& data);
void callerCalleeDataAvailable(const Data::CallerCalleeResults& data);
void eventsAvailable(const Data::EventResults& events);
void secondEventsAvailable(const Data::EventResults& events);
void parsingFinished();
void parsingFailed(const QString& errorMessage);
void progress(float progress);
Expand Down
1 change: 1 addition & 0 deletions src/startpage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ StartPage::StartPage(QWidget* parent)
connect(ui->recordDataButton, &QAbstractButton::clicked, this, &StartPage::recordButtonClicked);
connect(ui->stopParseButton, &QAbstractButton::clicked, this, &StartPage::stopParseButtonClicked);
connect(ui->pathSettings, &QAbstractButton::clicked, this, &StartPage::pathSettingsButtonClicked);
connect(ui->diffButton, &QAbstractButton::clicked, this, &StartPage::diffButtonClicked);
ui->openFileButton->setFocus();

updateBackground();
Expand Down
1 change: 1 addition & 0 deletions src/startpage.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public slots:
void recordButtonClicked();
void stopParseButtonClicked();
void pathSettingsButtonClicked();
void diffButtonClicked();

private:
void updateBackground();
Expand Down
Loading

0 comments on commit d0b37e5

Please sign in to comment.