Skip to content

Commit

Permalink
Add parallel_static_gcc and basic test coverage
Browse files Browse the repository at this point in the history
This is a somewhat more elaborate example which uses multiple
threads, lambdas and std::async which has the tendency to stress
our dwarf debug symbol resolution code. More on that in a follow-up
patch. For now, this test only uncovered an issue in
PerfParserTestClient::convertToText, where we iterated over a QHash
to generate text output, which is not going to produce stable results.
Instead, we now convert to a stable QMap first and output that.
Furthermore, the test harness is updated to also allow us to test
never version than 0.5 that we got in the past, i.e. 0.6 is now
expected for the new data files I'm adding here.

Change-Id: I2de65503b2c853528b301166a5b58a406d34a059
Reviewed-by: Ulf Hermann <[email protected]>
  • Loading branch information
milianw committed Jun 10, 2022
1 parent 990b8c2 commit bf8d70f
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 7 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ tests/auto/perfdata/vector_static_gcc/perf.data
tests/auto/perfdata/vector_static_gcc/perf.data.zstd
tests/auto/perfdata/vector_static_gcc/perf.lbr.data
tests/auto/perfdata/vector_static_gcc/vector_static_gcc_v9.1.0
tests/auto/perfdata/parallel_static_gcc/parallel_static_gcc
tests/auto/perfdata/parallel_static_gcc/perf.data.zstd
Binary file not shown.
Binary file not shown.
Binary file not shown.
20 changes: 13 additions & 7 deletions tests/auto/perfdata/tst_perfdata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ private slots:
};

static void setupUnwind(PerfUnwind *unwind, PerfHeader *header, QIODevice *input,
PerfAttributes *attributes, PerfData *data)
PerfAttributes *attributes, PerfData *data, const QByteArray &expectedVersion)
{
if (!header->isPipe()) {
const qint64 filePos = input->pos();
Expand All @@ -58,7 +58,7 @@ static void setupUnwind(PerfUnwind *unwind, PerfHeader *header, QIODevice *input

PerfTracingData tracingData = features.tracingData();
if (tracingData.size() > 0)
QCOMPARE(tracingData.version(), QByteArray("0.5"));
QCOMPARE(tracingData.version(), expectedVersion);

unwind->features(features);
const auto& attrs = attributes->attributes();
Expand All @@ -70,7 +70,7 @@ static void setupUnwind(PerfUnwind *unwind, PerfHeader *header, QIODevice *input
}
}

static void process(PerfUnwind *unwind, QIODevice *input)
static void process(PerfUnwind *unwind, QIODevice *input, const QByteArray &expectedVersion)
{
PerfHeader header(input);
PerfAttributes attributes;
Expand All @@ -79,7 +79,7 @@ static void process(PerfUnwind *unwind, QIODevice *input)

QSignalSpy spy(&data, SIGNAL(finished()));
QObject::connect(&header, &PerfHeader::finished, &data, [&](){
setupUnwind(unwind, &header, input, &attributes, &data);
setupUnwind(unwind, &header, input, &attributes, &data, expectedVersion);
data.read();
});

Expand Down Expand Up @@ -146,7 +146,7 @@ void TestPerfData::testTracingData()
"/lib/x86_64-linux-gnu/libc-2.24.so. "
"This can break stack unwinding and lead to missing symbols.")));
}
process(&unwind, &input);
process(&unwind, &input, QByteArray("0.5"));

if (stats) {
const PerfUnwind::Stats stats = unwind.stats();
Expand Down Expand Up @@ -200,7 +200,7 @@ void TestPerfData::testContentSize()

// Don't try to load any system files. They are not the same as the ones we use to report.
PerfUnwind unwind(&output, ":/", QString(), QString(), QString(), true);
process(&unwind, &input);
process(&unwind, &input, QByteArray("0.5"));

QCOMPARE(unwind.stats().numSamples, 69u);
}
Expand Down Expand Up @@ -254,13 +254,15 @@ void TestPerfData::testFiles_data()
uncompressFile(QFINDTESTDATA("vector_static_clang/vector_static_clang_v8.0.1.zlib"));
uncompressFile(QFINDTESTDATA("vector_static_gcc/vector_static_gcc_v9.1.0.zlib"));
uncompressFile(QFINDTESTDATA("fork_static_gcc/fork.zlib"));
uncompressFile(QFINDTESTDATA("parallel_static_gcc/parallel_static_gcc.zlib"));

const auto files = {
"vector_static_clang/perf.data",
"vector_static_gcc/perf.data",
"vector_static_gcc/perf.lbr.data",
"vector_static_gcc/perf.data.zstd",
"fork_static_gcc/perf.data.zstd",
"parallel_static_gcc/perf.data.zstd",
};
for (auto file : files)
QTest::addRow("%s", file) << file;
Expand Down Expand Up @@ -297,7 +299,11 @@ void TestPerfData::testFiles()
if (QTest::currentDataTag() != QLatin1String("fork_static_gcc/perf.data.zstd"))
QTest::ignoreMessage(QtWarningMsg, QRegularExpression("Failed to parse kernel symbol mapping file \".+\": Mapping is empty"));
unwind.setKallsymsPath(QProcess::nullDevice());
process(&unwind, &input);

auto version = QByteArray("0.5");
if (dataFile == "parallel_static_gcc/perf.data.zstd")
version = "0.6";
process(&unwind, &input, version);
}

output.close();
Expand Down
5 changes: 5 additions & 0 deletions tests/auto/shared/perfparsertestclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,12 @@ void PerfParserTestClient::convertToText(QTextStream &out) const
if (attribute.type == 2) {
const auto format = tracePointFormat(static_cast<qint32>(attribute.config));
out << string(format.system) << ' ' << string(format.name) << ' ' << Qt::hex << format.flags << Qt::dec << '\n';
// we need stable output to allow comparisons, so convert to map
QMap<qint32, QVariant> sortedTracePointData;
for (auto it = sample.tracePointData.begin(); it != sample.tracePointData.end(); ++it) {
sortedTracePointData.insert(it.key(), it.value());
}
for (auto it = sortedTracePointData.begin(); it != sortedTracePointData.end(); ++it) {
out << "\t\t" << string(it.key()) << '=' << it.value().toString() << '\n';
}
} else {
Expand Down
37 changes: 37 additions & 0 deletions tests/manual/clients/parallel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: LGPL-2.1-or-later

#include <cmath>
#include <complex>
#include <future>
#include <iostream>
#include <mutex>
#include <random>
#include <thread>
#include <vector>

using namespace std;

double worker()
{
uniform_real_distribution<double> uniform(-1E5, 1E5);
default_random_engine engine;
double s = 0;
for (int i = 0; i < 10000; ++i) {
s += norm(complex<double>(uniform(engine), uniform(engine)));
}
cout << s << endl;
return s;
}

int main(int argc, char** argv)
{
const int numTasks = argc > 1 ? stoi(argv[1]) : std::thread::hardware_concurrency();
vector<std::future<double>> results;
for (int i = 0; i < numTasks; ++i) {
results.push_back(async(launch::async, [i]() {
return worker() * i;
}));
}
return 0;
}

0 comments on commit bf8d70f

Please sign in to comment.