Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qbenchmarkvalgrind.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtTest/private/qbenchmark_p.h>
5
6#include <QtTest/private/qbenchmarkvalgrind_p.h>
7#include <QtCore/qstringlist.h>
8#include <QtCore/qcoreapplication.h>
9#include <QtCore/qprocess.h>
10#include <QtCore/qdir.h>
11#include <QtCore/qregularexpression.h>
12#include <QtCore/qset.h>
13#include <QtTest/private/callgrind_p.h>
14
15#include <charconv>
16#include <optional>
17
19
20using namespace Qt::StringLiterals;
21
22// Returns \c true if valgrind is available.
24{
25#ifdef NVALGRIND
26 return false;
27#else
28 QProcess process;
29 process.start(u"valgrind"_s, QStringList(u"--version"_s));
30 return process.waitForStarted() && process.waitForFinished(-1);
31#endif
32}
33
34// Reruns this program through callgrind.
35// Returns \c true upon success, otherwise false.
36bool QBenchmarkValgrindUtils::rerunThroughCallgrind(const QStringList &origAppArgs, int &exitCode)
37{
38 if (!QBenchmarkValgrindUtils::runCallgrindSubProcess(origAppArgs, exitCode)) {
39 qWarning("failed to run callgrind subprocess");
40 return false;
41 }
42 return true;
43}
44
45static void dumpOutput(const QByteArray &data, FILE *fh)
46{
47 QFile file;
50}
51
53{
55 const bool openOk = file.open(QIODevice::ReadOnly | QIODevice::Text);
56 Q_ASSERT(openOk);
57 Q_UNUSED(openOk);
58
59 std::optional<qint64> val = std::nullopt;
60 while (!file.atEnd()) {
61 const QByteArray line = file.readLine();
62 constexpr QByteArrayView tag = "summary: ";
63 if (line.startsWith(tag)) {
64 const auto maybeNumber = line.data() + tag.size();
65 const auto end = line.data() + line.size();
66 qint64 v;
67 const auto r = std::from_chars(maybeNumber, end, v);
68 if (r.ec == std::errc{}) {
69 val = v;
70 break;
71 }
72 }
73 }
74 if (Q_UNLIKELY(!val))
75 qFatal("Failed to extract result");
76 return *val;
77}
78
79// Gets the newest file name (i.e. the one with the highest integer suffix).
81{
82 QStringList nameFilters;
85
86 nameFilters << QString::fromLatin1("%1.*").arg(base);
87 const QFileInfoList fiList = QDir().entryInfoList(nameFilters, QDir::Files | QDir::Readable);
88 Q_ASSERT(!fiList.empty());
89 int hiSuffix = -1;
90 QFileInfo lastFileInfo;
91 const QString pattern = QString::fromLatin1("%1.(\\d+)").arg(base);
93 for (const QFileInfo &fileInfo : fiList) {
94 QRegularExpressionMatch match = rx.match(fileInfo.fileName());
95 Q_ASSERT(match.hasMatch());
96 bool ok;
97 const int suffix = match.captured(1).toInt(&ok);
98 Q_ASSERT(ok);
99 Q_ASSERT(suffix >= 0);
100 if (suffix > hiSuffix) {
101 lastFileInfo = fileInfo;
102 hiSuffix = suffix;
103 }
104 }
105
106 return lastFileInfo.fileName();
107}
108
110{
112}
113
115{
116 QStringList nameFilters;
119 nameFilters
120 << base // overall summary
121 << QString::fromLatin1("%1.*").arg(base); // individual dumps
122 const QFileInfoList fiList = QDir().entryInfoList(nameFilters, QDir::Files | QDir::Readable);
123 for (const QFileInfo &fileInfo : fiList) {
124 const bool removeOk = QFile::remove(fileInfo.fileName());
125 Q_ASSERT(removeOk);
126 Q_UNUSED(removeOk);
127 }
128}
129
131{
132 return QString::fromLatin1("callgrind.out.%1").arg(
133 pid != -1 ? pid : QCoreApplication::applicationPid());
134}
135
136// Reruns this program through callgrind, storing callgrind result files in the
137// current directory.
138// Returns \c true upon success, otherwise false.
140{
141 const QString &execFile = origAppArgs.at(0);
142 QStringList args{ u"--tool=callgrind"_s, u"--instr-atstart=yes"_s,
143 u"--quiet"_s, execFile, u"-callgrindchild"_s };
144
145 // pass on original arguments that make sense (e.g. avoid wasting time producing output
146 // that will be ignored anyway) ...
147 for (int i = 1; i < origAppArgs.size(); ++i) {
148 const QString &arg = origAppArgs.at(i);
149 if (arg == "-callgrind"_L1)
150 continue;
151 args << arg; // ok to pass on
152 }
153
154 QProcess process;
155 process.start(u"valgrind"_s, args);
156 process.waitForStarted(-1);
158 QBenchmarkValgrindUtils::outFileBase(process.processId());
159 const bool finishedOk = process.waitForFinished(-1);
160 exitCode = process.exitCode();
161
162 dumpOutput(process.readAllStandardOutput(), stdout);
163 dumpOutput(process.readAllStandardError(), stderr);
164
165 return finishedOk;
166}
167
169{
170 CALLGRIND_ZERO_STATS;
171}
172
174{
175 CALLGRIND_DUMP_STATS;
177 return { { qreal(result), QTest::InstructionReads } };
178}
179
181{
182 Q_UNUSED(measurement);
183 return true;
184}
185
187{
188 return 1;
189}
190
192{
193 return 1;
194}
195
197{
198 return true;
199}
200
bool isMeasurementAccepted(Measurement measurement) override
QList< Measurement > stop() override
static QBenchmarkGlobalData * current
static bool runCallgrindSubProcess(const QStringList &origAppArgs, int &exitCode)
static QString outFileBase(qint64 pid=-1)
static QString getNewestFileName()
static bool rerunThroughCallgrind(const QStringList &origAppArgs, int &exitCode)
static qint64 extractResult(const QString &fileName)
\inmodule QtCore
Definition qbytearray.h:57
static qint64 applicationPid() Q_DECL_CONST_FUNCTION
\inmodule QtCore
Definition qdir.h:19
QFileInfoList entryInfoList(Filters filters=NoFilter, SortFlags sort=NoSort) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qdir.cpp:1387
@ Files
Definition qdir.h:22
@ Readable
Definition qdir.h:28
bool atEnd() const override
Returns true if the end of the file has been reached; otherwise returns false.
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
QString fileName() const
Returns the name of the file, excluding the path.
\inmodule QtCore
Definition qfile.h:93
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:881
bool remove()
Removes the file specified by fileName().
Definition qfile.cpp:419
qint64 readLine(char *data, qint64 maxlen)
This function reads a line of ASCII characters from the device, up to a maximum of maxSize - 1 bytes,...
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
bool empty() const noexcept
Definition qlist.h:682
\inmodule QtCore \reentrant
\inmodule QtCore \reentrant
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5299
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5710
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
Definition qstring.cpp:8606
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QChar * data()
Returns a pointer to the data stored in the QString.
Definition qstring.h:1095
Combined button and popup list for selecting options.
static void dumpOutput(const QByteArray &data, FILE *fh)
#define Q_UNLIKELY(x)
AudioChannelLayoutTag tag
#define qWarning
Definition qlogging.h:162
#define qFatal
Definition qlogging.h:164
GLsizei const GLfloat * v
[13]
GLboolean r
[2]
GLuint GLuint end
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint GLfloat * val
GLuint64EXT * result
[6]
GLubyte * pattern
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
SSL_CTX int(*) void arg)
#define Q_UNUSED(x)
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
long long qint64
Definition qtypes.h:55
double qreal
Definition qtypes.h:92
QFile file
[0]
p rx()++
QJSValueList args