Qt 4.8
qbenchmarkvalgrind.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtTest module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "QtTest/private/qbenchmark_p.h"
43 
44 #ifdef QTESTLIB_USE_VALGRIND
45 
46 #include "QtTest/private/qbenchmarkvalgrind_p.h"
47 #include <QtCore/qstringlist.h>
48 #include <QtCore/qcoreapplication.h>
49 #include <QtCore/qprocess.h>
50 #include <QtCore/qdir.h>
51 #include <QtCore/qset.h>
52 #include "3rdparty/callgrind_p.h"
53 
55 
56 // Returns true iff a sufficiently recent valgrind is available.
58 {
59 #ifdef NVALGRIND
60  return false;
61 #else
62  QProcess process;
63  QStringList args;
64  args << QLatin1String("--version");
65  process.start(QLatin1String("valgrind"), args);
66  if (!process.waitForFinished(-1))
67  return false;
68  const QByteArray out = process.readAllStandardOutput();
69  const QRegExp rx(QLatin1String("^valgrind-([0-9]).([0-9]).[0-9]"));
70  if (rx.indexIn(QLatin1String(out.data())) == -1)
71  return false;
72  bool ok;
73  const int major = rx.cap(1).toInt(&ok);
74  if (!ok)
75  return false;
76  const int minor = rx.cap(2).toInt(&ok);
77  if (!ok)
78  return false;
79 // return (major > 3 || (major == 3 && minor >= 3)); // v >= 3.3 for --callgrind-out-file option
80  Q_UNUSED(major);
81  Q_UNUSED(minor);
82  return true; // skip version restriction for now
83 #endif
84 }
85 
86 // Reruns this program through callgrind.
87 // Returns true upon success, otherwise false.
88 bool QBenchmarkValgrindUtils::rerunThroughCallgrind(const QStringList &origAppArgs, int &exitCode)
89 {
90  if (!QBenchmarkValgrindUtils::runCallgrindSubProcess(origAppArgs, exitCode)) {
91  qWarning("failed to run callgrind subprocess");
92  return false;
93  }
94  return true;
95 }
96 
97 static void dumpOutput(const QByteArray &data, FILE *fh)
98 {
99  QFile file;
100  file.open(fh, QIODevice::WriteOnly);
101  file.write(data);
102 }
103 
105 {
106  QFile file(fileName);
107  const bool openOk = file.open(QIODevice::ReadOnly | QIODevice::Text);
108  Q_ASSERT(openOk);
109  Q_UNUSED(openOk);
110 
111  qint64 val = -1;
112  bool valSeen = false;
113  const QRegExp rxValue(QLatin1String("^summary: (\\d+)"));
114  while (!file.atEnd()) {
115  const QString line(QLatin1String(file.readLine()));
116  if (rxValue.indexIn(line) != -1) {
117  Q_ASSERT(rxValue.captureCount() == 1);
118  bool ok;
119  val = rxValue.cap(1).toLongLong(&ok);
120  Q_ASSERT(ok);
121  valSeen = true;
122  break;
123  }
124  }
125  Q_ASSERT(valSeen);
126  return val;
127 }
128 
129 // Gets the newest file name (i.e. the one with the highest integer suffix).
131 {
132  QStringList nameFilters;
134  Q_ASSERT(!base.isEmpty());
135 
136  nameFilters << QString::fromLatin1("%1.*").arg(base);
137  QFileInfoList fiList = QDir().entryInfoList(nameFilters, QDir::Files | QDir::Readable);
138  Q_ASSERT(!fiList.empty());
139  int hiSuffix = -1;
140  QFileInfo lastFileInfo;
141  const QString pattern = QString::fromLatin1("%1.(\\d+)").arg(base);
142  const QRegExp rx(pattern);
143  foreach (QFileInfo fileInfo, fiList) {
144  const int index = rx.indexIn(fileInfo.fileName());
145  Q_ASSERT(index == 0);
146  Q_UNUSED(index);
147  bool ok;
148  const int suffix = rx.cap(1).toInt(&ok);
149  Q_ASSERT(ok);
150  Q_ASSERT(suffix >= 0);
151  if (suffix > hiSuffix) {
152  lastFileInfo = fileInfo;
153  hiSuffix = suffix;
154  }
155  }
156 
157  return lastFileInfo.fileName();
158 }
159 
161 {
163 }
164 
166 {
167  QStringList nameFilters;
169  Q_ASSERT(!base.isEmpty());
170  nameFilters
171  << base // overall summary
172  << QString::fromLatin1("%1.*").arg(base); // individual dumps
173  QFileInfoList fiList = QDir().entryInfoList(nameFilters, QDir::Files | QDir::Readable);
174  foreach (QFileInfo fileInfo, fiList) {
175  const bool removeOk = QFile::remove(fileInfo.fileName());
176  Q_ASSERT(removeOk);
177  Q_UNUSED(removeOk);
178  }
179 }
180 
182 {
183  return QString::fromLatin1("callgrind.out.%1").arg(
184  pid != -1 ? pid : QCoreApplication::applicationPid());
185 }
186 
187 // Reruns this program through callgrind, storing callgrind result files in the
188 // current directory.
189 // Returns true upon success, otherwise false.
190 bool QBenchmarkValgrindUtils::runCallgrindSubProcess(const QStringList &origAppArgs, int &exitCode)
191 {
192  const QString execFile(origAppArgs.at(0));
193  QStringList args;
194  args << QLatin1String("--tool=callgrind") << QLatin1String("--instr-atstart=yes")
195  << QLatin1String("--quiet")
196  << execFile << QLatin1String("-callgrindchild");
197 
198 #if (defined Q_WS_QWS)
199  // While running the child process, we aren't processing events, and hence aren't
200  // acting as the QWS server. Therefore it's necessary to tell the child to act
201  // as its own server instead of connecting to us.
202  args << QLatin1String("-qws");
203 #endif
204 
205  // pass on original arguments that make sense (e.g. avoid wasting time producing output
206  // that will be ignored anyway) ...
207  for (int i = 1; i < origAppArgs.size(); ++i) {
208  const QString arg(origAppArgs.at(i));
209  if (arg == QLatin1String("-callgrind"))
210  continue;
211  args << arg; // ok to pass on
212  }
213 
214  QProcess process;
215  process.start(QLatin1String("valgrind"), args);
216  process.waitForStarted(-1);
219  const bool finishedOk = process.waitForFinished(-1);
220  exitCode = process.exitCode();
221 
222  dumpOutput(process.readAllStandardOutput(), stdout);
223  dumpOutput(process.readAllStandardError(), stderr);
224 
225  return finishedOk;
226 }
227 
228 #if defined(Q_CC_GNU) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)
229 // the callgrind macros below generate warnings
230 # pragma GCC diagnostic push
231 # pragma GCC diagnostic ignored "-Wunused-but-set-variable"
232 #endif
233 
235 {
237 }
238 
240 {
243  return result;
244 }
245 
246 #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)
247 // the callgrind macros above generate warnings
248 # pragma GCC diagnostic pop
249 #endif
250 
252 {
253  return checkpoint();
254 }
255 
257 {
258  Q_UNUSED(measurement);
259  return true;
260 }
261 
263 {
264  return 1;
265 }
266 
268 {
269  return 1;
270 }
271 
273 {
274  return true;
275 }
276 
278 {
280 }
281 
283 
284 #endif // QTESTLIB_USE_VALGRIND
static QString getNewestFileName()
The QDir class provides access to directory structures and their contents.
Definition: qdir.h:58
static bool rerunThroughCallgrind(const QStringList &origAppArgs, int &exitCode)
#define CALLGRIND_DUMP_STATS
Definition: callgrind_p.h:85
int exitCode() const
Returns the exit code of the last process that finished.
Definition: qprocess.cpp:2240
qlonglong toLongLong(bool *ok=0, int base=10) const
Returns the string converted to a long long using base base, which is 10 by default and must be betwe...
Definition: qstring.cpp:5943
static QString outFileBase(qint64 pid=-1)
static QBenchmarkGlobalData * current
Definition: qbenchmark_p.h:136
QString cap(int nth=0) const
Returns the text captured by the nth subexpression.
Definition: qregexp.cpp:4310
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
The QRegExp class provides pattern matching using regular expressions.
Definition: qregexp.h:61
int toInt(bool *ok=0, int base=10) const
Returns the string converted to an int using base base, which is 10 by default and must be between 2 ...
Definition: qstring.cpp:6090
bool open(OpenMode flags)
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition: qfile.cpp:1064
QBenchmarkMetric
This enum lists all the things that can be benchmarked.
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
QTest::QBenchmarkMetric metricType()
bool empty() const
This function is provided for STL compatibility.
Definition: qlist.h:304
QString fileName() const
Returns the name of the file, excluding the path.
Definition: qfileinfo.cpp:726
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
static bool runCallgrindSubProcess(const QStringList &origAppArgs, int &exitCode)
The QString class provides a Unicode character string.
Definition: qstring.h:83
Q_PID pid() const
Returns the native process identifier for the running process, if available.
Definition: qprocess.cpp:1581
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
static const uint base
Definition: qurl.cpp:268
#define CALLGRIND_ZERO_STATS
Definition: callgrind_p.h:104
QString callgrindOutFileBase
Definition: qbenchmark_p.h:153
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
bool waitForFinished(int msecs=30000)
Blocks until the process has finished and the finished() signal has been emitted, or until msecs mill...
Definition: qprocess.cpp:1863
int indexIn(const QString &str, int offset=0, CaretMode caretMode=CaretAtZero) const
Attempts to find a match in str from position offset (0 by default).
Definition: qregexp.cpp:4136
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
Q_CORE_EXPORT void qWarning(const char *,...)
static qint64 applicationPid()
Returns the current process ID for the application.
static const char * data(const QByteArray &arr)
QFileInfoList entryInfoList(Filters filters=NoFilter, SortFlags sort=NoSort) const
Returns a list of QFileInfo objects for all the files and directories in the directory, ordered according to the name and attribute filters previously set with setNameFilters() and setFilter(), and sorted according to the flags set with setSorting().
Definition: qdir.cpp:1316
static void dumpOutput(const QByteArray &data, FILE *fh)
__int64 qint64
Definition: qglobal.h:942
QByteArray readAllStandardError()
Regardless of the current read channel, this function returns all data available from the standard er...
Definition: qprocess.cpp:2029
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
The QFile class provides an interface for reading from and writing to files.
Definition: qfile.h:65
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...
Definition: qiodevice.cpp:1110
int captureCount() const
Returns the number of captures contained in the regular expression.
Definition: qregexp.cpp:4223
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
static qint64 extractResult(const QString &fileName)
QByteArray suffix
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
bool isMeasurementAccepted(qint64 measurement)
bool remove()
Removes the file specified by fileName().
Definition: qfile.cpp:715
quint16 index
void start(const QString &program, const QStringList &arguments, OpenMode mode=ReadWrite)
Starts the given program in a new process, if none is already running, passing the command line argum...
Definition: qprocess.cpp:2060
QByteArray readAllStandardOutput()
Regardless of the current read channel, this function returns all data available from the standard ou...
Definition: qprocess.cpp:2013
bool waitForStarted(int msecs=30000)
Blocks until the process has started and the started() signal has been emitted, or until msecs millis...
Definition: qprocess.cpp:1800
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
Definition: qiodevice.cpp:1342
The QFileInfo class provides system-independent file information.
Definition: qfileinfo.h:60
bool atEnd() const
Returns true if the end of the file has been reached; otherwise returns false.
Definition: qfile.cpp:1735
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
static QString fileName(const QString &fileUrl)
The QProcess class is used to start external programs and to communicate with them.
Definition: qprocess.h:102