Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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;
48 if (!file.open(fh, QIODevice::WriteOnly)) {
49 qFatal("Could not open filehandle for dumping output: %s",
51 }
53}
54
56{
58 const bool openOk = file.open(QIODevice::ReadOnly | QIODevice::Text);
59 Q_ASSERT(openOk);
60 Q_UNUSED(openOk);
61
62 std::optional<qint64> val = std::nullopt;
63 while (!file.atEnd()) {
64 const QByteArray line = file.readLine();
65 constexpr QByteArrayView tag = "summary: ";
66 if (line.startsWith(tag)) {
67 const auto maybeNumber = line.data() + tag.size();
68 const auto end = line.data() + line.size();
69 qint64 v;
70 const auto r = std::from_chars(maybeNumber, end, v);
71 if (r.ec == std::errc{}) {
72 val = v;
73 break;
74 }
75 }
76 }
77 if (Q_UNLIKELY(!val))
78 qFatal("Failed to extract result");
79 return *val;
80}
81
82// Gets the newest file name (i.e. the one with the highest integer suffix).
84{
85 QStringList nameFilters;
86 QString base = QBenchmarkGlobalData::current->callgrindOutFileBase;
87 Q_ASSERT(!base.isEmpty());
88
89 nameFilters << QString::fromLatin1("%1.*").arg(base);
90 const QFileInfoList fiList = QDir().entryInfoList(nameFilters, QDir::Files | QDir::Readable);
91 Q_ASSERT(!fiList.empty());
92 int hiSuffix = -1;
93 QFileInfo lastFileInfo;
94 const QString pattern = QString::fromLatin1("%1.(\\d+)").arg(base);
96 for (const QFileInfo &fileInfo : fiList) {
97 QRegularExpressionMatch match = rx.match(fileInfo.fileName());
98 Q_ASSERT(match.hasMatch());
99 bool ok;
100 const int suffix = match.captured(1).toInt(&ok);
101 Q_ASSERT(ok);
102 Q_ASSERT(suffix >= 0);
103 if (suffix > hiSuffix) {
104 lastFileInfo = fileInfo;
105 hiSuffix = suffix;
106 }
107 }
108
109 return lastFileInfo.fileName();
110}
111
116
118{
119 QStringList nameFilters;
120 QString base = QBenchmarkGlobalData::current->callgrindOutFileBase;
121 Q_ASSERT(!base.isEmpty());
122 nameFilters
123 << base // overall summary
124 << QString::fromLatin1("%1.*").arg(base); // individual dumps
125 const QFileInfoList fiList = QDir().entryInfoList(nameFilters, QDir::Files | QDir::Readable);
126 for (const QFileInfo &fileInfo : fiList) {
127 const bool removeOk = QFile::remove(fileInfo.fileName());
128 Q_ASSERT(removeOk);
129 Q_UNUSED(removeOk);
130 }
131}
132
134{
135 return QString::fromLatin1("callgrind.out.%1").arg(
136 pid != -1 ? pid : QCoreApplication::applicationPid());
137}
138
139// Reruns this program through callgrind, storing callgrind result files in the
140// current directory.
141// Returns \c true upon success, otherwise false.
143{
144 const QString &execFile = origAppArgs.at(0);
145 QStringList args{ u"--tool=callgrind"_s, u"--instr-atstart=yes"_s,
146 u"--quiet"_s, execFile, u"-callgrindchild"_s };
147
148 // pass on original arguments that make sense (e.g. avoid wasting time producing output
149 // that will be ignored anyway) ...
150 for (int i = 1; i < origAppArgs.size(); ++i) {
151 const QString &arg = origAppArgs.at(i);
152 if (arg == "-callgrind"_L1)
153 continue;
154 args << arg; // ok to pass on
155 }
156
157 QProcess process;
158 process.start(u"valgrind"_s, args);
159 process.waitForStarted(-1);
160 QBenchmarkGlobalData::current->callgrindOutFileBase =
161 QBenchmarkValgrindUtils::outFileBase(process.processId());
162 const bool finishedOk = process.waitForFinished(-1);
163 exitCode = process.exitCode();
164
165 dumpOutput(process.readAllStandardOutput(), stdout);
166 dumpOutput(process.readAllStandardError(), stderr);
167
168 return finishedOk;
169}
170
172{
173 CALLGRIND_ZERO_STATS;
174}
175
176QList<QBenchmarkMeasurerBase::Measurement> QBenchmarkCallgrindMeasurer::stop()
177{
178 CALLGRIND_DUMP_STATS;
180 return { { qreal(result), QTest::InstructionReads } };
181}
182
184{
185 Q_UNUSED(measurement);
186 return true;
187}
188
193
195{
196 return 1;
197}
198
203
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:20
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:1388
@ Files
Definition qdir.h:23
@ Readable
Definition qdir.h:29
bool atEnd() const override
Returns true if the end of the file has been reached; otherwise returns false.
\inmodule QtCore
Definition qfile.h:93
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:904
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.
QString errorString() const
Returns a human-readable description of the last device error that occurred.
\inmodule QtCore \reentrant
\inmodule QtCore \reentrant
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
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:5455
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1226
QChar * data()
Returns a pointer to the data stored in the QString.
Definition qstring.h:1240
Combined button and popup list for selecting options.
static void dumpOutput(const QByteArray &data, FILE *fh)
#define Q_UNLIKELY(x)
QList< QString > QStringList
Constructs a string list that contains the given string, str.
AudioChannelLayoutTag tag
#define qWarning
Definition qlogging.h:166
#define qFatal
Definition qlogging.h:168
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 qPrintable(string)
Definition qstring.h:1531
#define Q_UNUSED(x)
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
long long qint64
Definition qtypes.h:60
double qreal
Definition qtypes.h:187
static const uint base
Definition qurlidna.cpp:20
QFile file
[0]
p rx()++
QJSValueList args