qbenchmarkvalgrind.cpp

Source codeSwitch to Preprocessed file
LineSource CodeCoverage
1/**************************************************************************** -
2** -
3** Copyright (C) 2013 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 <QtTest/private/callgrind_p.h> -
53 -
54QT_BEGIN_NAMESPACE -
55 -
56// Returns true iff a sufficiently recent valgrind is available. -
57bool QBenchmarkValgrindUtils::haveValgrind() -
58{ -
59#ifdef NVALGRIND -
60 return false; -
61#else -
62 QProcess process;
never executed (the execution status of this line is deduced): QProcess process;
-
63 QStringList args;
never executed (the execution status of this line is deduced): QStringList args;
-
64 args << QLatin1String("--version");
never executed (the execution status of this line is deduced): args << QLatin1String("--version");
-
65 process.start(QLatin1String("valgrind"), args);
never executed (the execution status of this line is deduced): process.start(QLatin1String("valgrind"), args);
-
66 if (!process.waitForFinished(-1))
never evaluated: !process.waitForFinished(-1)
0
67 return false;
never executed: return false;
0
68 const QByteArray out = process.readAllStandardOutput();
never executed (the execution status of this line is deduced): const QByteArray out = process.readAllStandardOutput();
-
69 QRegExp rx(QLatin1String("^valgrind-([0-9]).([0-9]).[0-9]"));
never executed (the execution status of this line is deduced): QRegExp rx(QLatin1String("^valgrind-([0-9]).([0-9]).[0-9]"));
-
70 if (rx.indexIn(QLatin1String(out.data())) == -1)
never evaluated: rx.indexIn(QLatin1String(out.data())) == -1
0
71 return false;
never executed: return false;
0
72 bool ok;
never executed (the execution status of this line is deduced): bool ok;
-
73 const int major = rx.cap(1).toInt(&ok);
never executed (the execution status of this line is deduced): const int major = rx.cap(1).toInt(&ok);
-
74 if (!ok)
never evaluated: !ok
0
75 return false;
never executed: return false;
0
76 const int minor = rx.cap(2).toInt(&ok);
never executed (the execution status of this line is deduced): const int minor = rx.cap(2).toInt(&ok);
-
77 if (!ok)
never evaluated: !ok
0
78 return false;
never executed: return false;
0
79// return (major > 3 || (major == 3 && minor >= 3)); // v >= 3.3 for --callgrind-out-file option -
80 Q_UNUSED(major);
never executed (the execution status of this line is deduced): (void)major;;
-
81 Q_UNUSED(minor);
never executed (the execution status of this line is deduced): (void)minor;;
-
82 return true; // skip version restriction for now
never executed: return true;
0
83#endif -
84} -
85 -
86// Reruns this program through callgrind. -
87// Returns true upon success, otherwise false. -
88bool QBenchmarkValgrindUtils::rerunThroughCallgrind(const QStringList &origAppArgs, int &exitCode) -
89{ -
90 if (!QBenchmarkValgrindUtils::runCallgrindSubProcess(origAppArgs, exitCode)) {
never evaluated: !QBenchmarkValgrindUtils::runCallgrindSubProcess(origAppArgs, exitCode)
0
91 qWarning("failed to run callgrind subprocess");
never executed (the execution status of this line is deduced): QMessageLogger("qbenchmarkvalgrind.cpp", 91, __PRETTY_FUNCTION__).warning("failed to run callgrind subprocess");
-
92 return false;
never executed: return false;
0
93 } -
94 return true;
never executed: return true;
0
95} -
96 -
97static void dumpOutput(const QByteArray &data, FILE *fh) -
98{ -
99 QFile file;
never executed (the execution status of this line is deduced): QFile file;
-
100 file.open(fh, QIODevice::WriteOnly);
never executed (the execution status of this line is deduced): file.open(fh, QIODevice::WriteOnly);
-
101 file.write(data);
never executed (the execution status of this line is deduced): file.write(data);
-
102}
never executed: }
0
103 -
104qint64 QBenchmarkValgrindUtils::extractResult(const QString &fileName) -
105{ -
106 QFile file(fileName);
never executed (the execution status of this line is deduced): QFile file(fileName);
-
107 const bool openOk = file.open(QIODevice::ReadOnly | QIODevice::Text);
never executed (the execution status of this line is deduced): const bool openOk = file.open(QIODevice::ReadOnly | QIODevice::Text);
-
108 Q_ASSERT(openOk);
never executed (the execution status of this line is deduced): qt_noop();
-
109 Q_UNUSED(openOk);
never executed (the execution status of this line is deduced): (void)openOk;;
-
110 -
111 qint64 val = -1;
never executed (the execution status of this line is deduced): qint64 val = -1;
-
112 bool valSeen = false;
never executed (the execution status of this line is deduced): bool valSeen = false;
-
113 QRegExp rxValue(QLatin1String("^summary: (\\d+)"));
never executed (the execution status of this line is deduced): QRegExp rxValue(QLatin1String("^summary: (\\d+)"));
-
114 while (!file.atEnd()) {
never evaluated: !file.atEnd()
0
115 const QString line(QLatin1String(file.readLine()));
never executed (the execution status of this line is deduced): const QString line(QLatin1String(file.readLine()));
-
116 if (rxValue.indexIn(line) != -1) {
never evaluated: rxValue.indexIn(line) != -1
0
117 Q_ASSERT(rxValue.captureCount() == 1);
never executed (the execution status of this line is deduced): qt_noop();
-
118 bool ok;
never executed (the execution status of this line is deduced): bool ok;
-
119 val = rxValue.cap(1).toLongLong(&ok);
never executed (the execution status of this line is deduced): val = rxValue.cap(1).toLongLong(&ok);
-
120 Q_ASSERT(ok);
never executed (the execution status of this line is deduced): qt_noop();
-
121 valSeen = true;
never executed (the execution status of this line is deduced): valSeen = true;
-
122 break;
never executed: break;
0
123 } -
124 }
never executed: }
0
125 if (!valSeen)
never evaluated: !valSeen
0
126 qFatal("Failed to extract result");
never executed: QMessageLogger("qbenchmarkvalgrind.cpp", 126, __PRETTY_FUNCTION__).fatal("Failed to extract result");
0
127 return val;
never executed: return val;
0
128} -
129 -
130// Gets the newest file name (i.e. the one with the highest integer suffix). -
131QString QBenchmarkValgrindUtils::getNewestFileName() -
132{ -
133 QStringList nameFilters;
never executed (the execution status of this line is deduced): QStringList nameFilters;
-
134 QString base = QBenchmarkGlobalData::current->callgrindOutFileBase;
never executed (the execution status of this line is deduced): QString base = QBenchmarkGlobalData::current->callgrindOutFileBase;
-
135 Q_ASSERT(!base.isEmpty());
never executed (the execution status of this line is deduced): qt_noop();
-
136 -
137 nameFilters << QString::fromLatin1("%1.*").arg(base);
never executed (the execution status of this line is deduced): nameFilters << QString::fromLatin1("%1.*").arg(base);
-
138 QFileInfoList fiList = QDir().entryInfoList(nameFilters, QDir::Files | QDir::Readable);
never executed (the execution status of this line is deduced): QFileInfoList fiList = QDir().entryInfoList(nameFilters, QDir::Files | QDir::Readable);
-
139 Q_ASSERT(!fiList.empty());
never executed (the execution status of this line is deduced): qt_noop();
-
140 int hiSuffix = -1;
never executed (the execution status of this line is deduced): int hiSuffix = -1;
-
141 QFileInfo lastFileInfo;
never executed (the execution status of this line is deduced): QFileInfo lastFileInfo;
-
142 const QString pattern = QString::fromLatin1("%1.(\\d+)").arg(base);
never executed (the execution status of this line is deduced): const QString pattern = QString::fromLatin1("%1.(\\d+)").arg(base);
-
143 QRegExp rx(pattern);
never executed (the execution status of this line is deduced): QRegExp rx(pattern);
-
144 foreach (const QFileInfo &fileInfo, fiList) {
never executed (the execution status of this line is deduced): for (QForeachContainer<__typeof__(fiList)> _container_(fiList); !_container_.brk && _container_.i != _container_.e; __extension__ ({ ++_container_.brk; ++_container_.i; })) for (const QFileInfo &fileInfo = *_container_.i;; __extension__ ({--_container_.brk; break;})) {
-
145 const int index = rx.indexIn(fileInfo.fileName());
never executed (the execution status of this line is deduced): const int index = rx.indexIn(fileInfo.fileName());
-
146 Q_ASSERT(index == 0);
never executed (the execution status of this line is deduced): qt_noop();
-
147 Q_UNUSED(index);
never executed (the execution status of this line is deduced): (void)index;;
-
148 bool ok;
never executed (the execution status of this line is deduced): bool ok;
-
149 const int suffix = rx.cap(1).toInt(&ok);
never executed (the execution status of this line is deduced): const int suffix = rx.cap(1).toInt(&ok);
-
150 Q_ASSERT(ok);
never executed (the execution status of this line is deduced): qt_noop();
-
151 Q_ASSERT(suffix >= 0);
never executed (the execution status of this line is deduced): qt_noop();
-
152 if (suffix > hiSuffix) {
never evaluated: suffix > hiSuffix
0
153 lastFileInfo = fileInfo;
never executed (the execution status of this line is deduced): lastFileInfo = fileInfo;
-
154 hiSuffix = suffix;
never executed (the execution status of this line is deduced): hiSuffix = suffix;
-
155 }
never executed: }
0
156 }
never executed: }
0
157 -
158 return lastFileInfo.fileName();
never executed: return lastFileInfo.fileName();
0
159} -
160 -
161qint64 QBenchmarkValgrindUtils::extractLastResult() -
162{ -
163 return extractResult(getNewestFileName());
never executed: return extractResult(getNewestFileName());
0
164} -
165 -
166void QBenchmarkValgrindUtils::cleanup() -
167{ -
168 QStringList nameFilters;
never executed (the execution status of this line is deduced): QStringList nameFilters;
-
169 QString base = QBenchmarkGlobalData::current->callgrindOutFileBase;
never executed (the execution status of this line is deduced): QString base = QBenchmarkGlobalData::current->callgrindOutFileBase;
-
170 Q_ASSERT(!base.isEmpty());
never executed (the execution status of this line is deduced): qt_noop();
-
171 nameFilters
never executed (the execution status of this line is deduced): nameFilters
-
172 << base // overall summary
never executed (the execution status of this line is deduced): << base
-
173 << QString::fromLatin1("%1.*").arg(base); // individual dumps
never executed (the execution status of this line is deduced): << QString::fromLatin1("%1.*").arg(base);
-
174 QFileInfoList fiList = QDir().entryInfoList(nameFilters, QDir::Files | QDir::Readable);
never executed (the execution status of this line is deduced): QFileInfoList fiList = QDir().entryInfoList(nameFilters, QDir::Files | QDir::Readable);
-
175 foreach (const QFileInfo &fileInfo, fiList) {
never executed (the execution status of this line is deduced): for (QForeachContainer<__typeof__(fiList)> _container_(fiList); !_container_.brk && _container_.i != _container_.e; __extension__ ({ ++_container_.brk; ++_container_.i; })) for (const QFileInfo &fileInfo = *_container_.i;; __extension__ ({--_container_.brk; break;})) {
-
176 const bool removeOk = QFile::remove(fileInfo.fileName());
never executed (the execution status of this line is deduced): const bool removeOk = QFile::remove(fileInfo.fileName());
-
177 Q_ASSERT(removeOk);
never executed (the execution status of this line is deduced): qt_noop();
-
178 Q_UNUSED(removeOk);
never executed (the execution status of this line is deduced): (void)removeOk;;
-
179 }
never executed: }
0
180}
never executed: }
0
181 -
182QString QBenchmarkValgrindUtils::outFileBase(qint64 pid) -
183{ -
184 return QString::fromLatin1("callgrind.out.%1").arg(
never executed: return QString::fromLatin1("callgrind.out.%1").arg( pid != -1 ? pid : QCoreApplication::applicationPid());
0
185 pid != -1 ? pid : QCoreApplication::applicationPid());
never executed: return QString::fromLatin1("callgrind.out.%1").arg( pid != -1 ? pid : QCoreApplication::applicationPid());
0
186} -
187 -
188// Reruns this program through callgrind, storing callgrind result files in the -
189// current directory. -
190// Returns true upon success, otherwise false. -
191bool QBenchmarkValgrindUtils::runCallgrindSubProcess(const QStringList &origAppArgs, int &exitCode) -
192{ -
193 const QString execFile(origAppArgs.at(0));
never executed (the execution status of this line is deduced): const QString execFile(origAppArgs.at(0));
-
194 QStringList args;
never executed (the execution status of this line is deduced): QStringList args;
-
195 args << QLatin1String("--tool=callgrind") << QLatin1String("--instr-atstart=yes")
never executed (the execution status of this line is deduced): args << QLatin1String("--tool=callgrind") << QLatin1String("--instr-atstart=yes")
-
196 << QLatin1String("--quiet")
never executed (the execution status of this line is deduced): << QLatin1String("--quiet")
-
197 << execFile << QLatin1String("-callgrindchild");
never executed (the execution status of this line is deduced): << execFile << QLatin1String("-callgrindchild");
-
198 -
199 // pass on original arguments that make sense (e.g. avoid wasting time producing output -
200 // that will be ignored anyway) ... -
201 for (int i = 1; i < origAppArgs.size(); ++i) {
never evaluated: i < origAppArgs.size()
0
202 const QString arg(origAppArgs.at(i));
never executed (the execution status of this line is deduced): const QString arg(origAppArgs.at(i));
-
203 if (arg == QLatin1String("-callgrind"))
never evaluated: arg == QLatin1String("-callgrind")
0
204 continue;
never executed: continue;
0
205 args << arg; // ok to pass on
never executed (the execution status of this line is deduced): args << arg;
-
206 }
never executed: }
0
207 -
208 QProcess process;
never executed (the execution status of this line is deduced): QProcess process;
-
209 process.start(QLatin1String("valgrind"), args);
never executed (the execution status of this line is deduced): process.start(QLatin1String("valgrind"), args);
-
210 process.waitForStarted(-1);
never executed (the execution status of this line is deduced): process.waitForStarted(-1);
-
211 QBenchmarkGlobalData::current->callgrindOutFileBase =
never executed (the execution status of this line is deduced): QBenchmarkGlobalData::current->callgrindOutFileBase =
-
212 QBenchmarkValgrindUtils::outFileBase(process.pid());
never executed (the execution status of this line is deduced): QBenchmarkValgrindUtils::outFileBase(process.pid());
-
213 const bool finishedOk = process.waitForFinished(-1);
never executed (the execution status of this line is deduced): const bool finishedOk = process.waitForFinished(-1);
-
214 exitCode = process.exitCode();
never executed (the execution status of this line is deduced): exitCode = process.exitCode();
-
215 -
216 dumpOutput(process.readAllStandardOutput(), stdout);
never executed (the execution status of this line is deduced): dumpOutput(process.readAllStandardOutput(), stdout);
-
217 dumpOutput(process.readAllStandardError(), stderr);
never executed (the execution status of this line is deduced): dumpOutput(process.readAllStandardError(), stderr);
-
218 -
219 return finishedOk;
never executed: return finishedOk;
0
220} -
221 -
222void QBenchmarkCallgrindMeasurer::start() -
223{ -
224 CALLGRIND_ZERO_STATS;
never executed (the execution status of this line is deduced): {unsigned int _qzz_res; { volatile unsigned long long int _zzq_args[6]; volatile unsigned long long int _zzq_result; _zzq_args[0] = (unsigned long long int)(VG_USERREQ__ZERO_STATS); _zzq_args[1] = (unsigned long long int)(0); _zzq_args[2] = (unsigned long long int)(0); _zzq_args[3] = (unsigned long long int)(0); _zzq_args[4] = (unsigned long long int)(0); _zzq_args[5] = (unsigned long long int)(0); __asm__ volatile("rolq $3, %%rdi ; rolq $13, %%rdi\n\t" "rolq $61, %%rdi ; rolq $51, %%rdi\n\t" "xchgq %%rbx,%%rbx" : "=d" (_zzq_result) : "a" (&_zzq_args[0]), "0" (0) : "cc", "memory" ); _qzz_res = _zzq_result; (void)_qzz_res; }; };
-
225}
never executed: }
0
226 -
227qint64 QBenchmarkCallgrindMeasurer::checkpoint() -
228{ -
229 CALLGRIND_DUMP_STATS;
never executed (the execution status of this line is deduced): {unsigned int _qzz_res; { volatile unsigned long long int _zzq_args[6]; volatile unsigned long long int _zzq_result; _zzq_args[0] = (unsigned long long int)(VG_USERREQ__DUMP_STATS); _zzq_args[1] = (unsigned long long int)(0); _zzq_args[2] = (unsigned long long int)(0); _zzq_args[3] = (unsigned long long int)(0); _zzq_args[4] = (unsigned long long int)(0); _zzq_args[5] = (unsigned long long int)(0); __asm__ volatile("rolq $3, %%rdi ; rolq $13, %%rdi\n\t" "rolq $61, %%rdi ; rolq $51, %%rdi\n\t" "xchgq %%rbx,%%rbx" : "=d" (_zzq_result) : "a" (&_zzq_args[0]), "0" (0) : "cc", "memory" ); _qzz_res = _zzq_result; (void)_qzz_res; }; };
-
230 const qint64 result = QBenchmarkValgrindUtils::extractLastResult();
never executed (the execution status of this line is deduced): const qint64 result = QBenchmarkValgrindUtils::extractLastResult();
-
231 return result;
never executed: return result;
0
232} -
233 -
234qint64 QBenchmarkCallgrindMeasurer::stop() -
235{ -
236 return checkpoint();
never executed: return checkpoint();
0
237} -
238 -
239bool QBenchmarkCallgrindMeasurer::isMeasurementAccepted(qint64 measurement) -
240{ -
241 Q_UNUSED(measurement);
never executed (the execution status of this line is deduced): (void)measurement;;
-
242 return true;
never executed: return true;
0
243} -
244 -
245int QBenchmarkCallgrindMeasurer::adjustIterationCount(int) -
246{ -
247 return 1;
never executed: return 1;
0
248} -
249 -
250int QBenchmarkCallgrindMeasurer::adjustMedianCount(int) -
251{ -
252 return 1;
never executed: return 1;
0
253} -
254 -
255bool QBenchmarkCallgrindMeasurer::needsWarmupIteration() -
256{ -
257 return true;
never executed: return true;
0
258} -
259 -
260QTest::QBenchmarkMetric QBenchmarkCallgrindMeasurer::metricType() -
261{ -
262 return QTest::InstructionReads;
never executed: return QTest::InstructionReads;
0
263} -
264 -
265QT_END_NAMESPACE -
266 -
267#endif // QTESTLIB_USE_VALGRIND -
268 -
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial