Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qbenchmark.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
/
qbenchmark
.
h
>
5
#
include
<
QtTest
/
private
/
qbenchmark_p
.
h
>
6
#
include
<
QtTest
/
private
/
qbenchmarkmetric_p
.
h
>
7
#
include
<
QtTest
/
private
/
qbenchmarktimemeasurers_p
.
h
>
8
9
#
include
<
QtCore
/
qdir
.
h
>
10
#
include
<
QtCore
/
qset
.
h
>
11
#
include
<
QtCore
/
qdebug
.
h
>
12
13
QT_BEGIN_NAMESPACE
14
15
QBenchmarkGlobalData
*QBenchmarkGlobalData::current;
16
17
QBenchmarkGlobalData::QBenchmarkGlobalData()
18
{
19
setMode(mode_);
20
}
21
22
QBenchmarkGlobalData::~QBenchmarkGlobalData()
23
{
24
delete
measurer;
25
if
(QBenchmarkGlobalData::current ==
this
)
26
QBenchmarkGlobalData::current =
nullptr
;
27
}
28
29
void
QBenchmarkGlobalData::setMode(Mode mode)
30
{
31
mode_ = mode;
32
33
delete
measurer;
34
measurer = createMeasurer();
35
}
36
37
QBenchmarkMeasurerBase * QBenchmarkGlobalData::createMeasurer()
38
{
39
QBenchmarkMeasurerBase *measurer =
nullptr
;
40
if
(0) {
41
#
if
QT_CONFIG
(
valgrind
)
42
}
else
if
(mode_ == CallgrindChildProcess || mode_ == CallgrindParentProcess) {
43
measurer =
new
QBenchmarkCallgrindMeasurer;
44
#
endif
45
#
ifdef
QTESTLIB_USE_PERF_EVENTS
46
}
else
if
(mode_ == PerfCounter) {
47
measurer =
new
QBenchmarkPerfEventsMeasurer;
48
#
endif
49
#
ifdef
HAVE_TICK_COUNTER
50
}
else
if
(mode_ == TickCounter) {
51
measurer =
new
QBenchmarkTickMeasurer;
52
#
endif
53
}
else
if
(mode_ == EventCounter) {
54
measurer =
new
QBenchmarkEvent;
55
}
else
{
56
measurer =
new
QBenchmarkTimeMeasurer;
57
}
58
return
measurer;
59
}
60
61
int
QBenchmarkGlobalData::adjustMedianIterationCount()
62
{
63
return
medianIterationCount != -1
64
? medianIterationCount : measurer->adjustMedianCount(1);
65
}
66
67
68
QBenchmarkTestMethodData *QBenchmarkTestMethodData::current;
69
70
QBenchmarkTestMethodData::QBenchmarkTestMethodData() =
default
;
71
72
QBenchmarkTestMethodData::~QBenchmarkTestMethodData()
73
{
74
QBenchmarkTestMethodData::current =
nullptr
;
75
}
76
77
void
QBenchmarkTestMethodData::beginDataRun()
78
{
79
iterationCount = initialIterationCount(1);
80
}
81
82
void
QBenchmarkTestMethodData::endDataRun()
83
{
84
}
85
86
/*!
87
\internal
88
Initial iteration count based on \a suggestion.
89
90
In qtestcase.cpp, TestMethods::invokeTestOnData() invokes the test method in
91
a loop until (the test fails or skips, or) the test run's duration exceeds a
92
certain minimum; setResults() doubles \c iterationCount when it doesn't
93
accept the result. In each call to the test method, the QBENCHMARK duly
94
performs \c iteractionCount cycles of its block of code, from which other
95
things make the above decisions about whether to double and try again.
96
*/
97
int
QBenchmarkTestMethodData::initialIterationCount(
int
suggestion)
const
98
{
99
// Let the -iterations option override the measurer.
100
if
(QBenchmarkGlobalData::current->iterationCount != -1)
101
return
QBenchmarkGlobalData::current->iterationCount;
102
103
return
QBenchmarkGlobalData::current->measurer->adjustIterationCount(suggestion);
104
}
105
106
void
QBenchmarkTestMethodData::setResults(
const
QList<QBenchmarkMeasurerBase::Measurement> &list,
107
bool
setByMacro)
108
{
109
bool
accepted =
false
;
110
QBenchmarkMeasurerBase::Measurement firstMeasurement = {};
111
if
(!list.isEmpty())
112
firstMeasurement = list.constFirst();
113
114
// Always accept the result if the iteration count has been
115
// specified on the command line with -iterations.
116
if
(QBenchmarkGlobalData::current->iterationCount != -1)
117
accepted =
true
;
118
119
else
if
(QBenchmarkTestMethodData::current->runOnce || !setByMacro) {
120
iterationCount = 1;
121
accepted =
true
;
122
}
123
124
// Test the result directly without calling the measurer if the minimum time
125
// has been specified on the command line with -minimumvalue.
126
else
if
(QBenchmarkGlobalData::current->walltimeMinimum != -1)
127
accepted = (firstMeasurement.value > QBenchmarkGlobalData::current->walltimeMinimum);
128
else
129
accepted = QBenchmarkGlobalData::current->measurer->isMeasurementAccepted(firstMeasurement);
130
131
QBenchmarkGlobalData::current->measurer->resetMetricsResults();
132
// Accept the result or double the number of iterations.
133
if
(accepted)
134
resultAccepted =
true
;
135
else
136
iterationCount *= 2;
137
138
valid =
true
;
139
results.reserve(list.size());
140
for
(
auto
m : list)
141
results.emplaceBack(QBenchmarkGlobalData::current->context, m, iterationCount, setByMacro);
142
}
143
144
/*!
145
\class QTest::QBenchmarkIterationController
146
\internal
147
148
The QBenchmarkIterationController class is used by the QBENCHMARK macro to
149
drive the benchmarking loop. It is responsible for starting and stopping
150
the timing measurements as well as calling the result reporting functions.
151
*/
152
153
/*! \internal
154
*/
155
QTest::QBenchmarkIterationController::QBenchmarkIterationController(RunMode runMode)
156
{
157
i = 0;
158
QBenchmarkTestMethodData::current->setBlockSize();
159
if
(runMode == RunOnce)
160
QBenchmarkTestMethodData::current->runOnce =
true
;
161
QTest::beginBenchmarkMeasurement();
162
}
163
164
QTest::QBenchmarkIterationController::QBenchmarkIterationController()
165
{
166
i = 0;
167
QBenchmarkTestMethodData::current->setBlockSize();
168
QTest::beginBenchmarkMeasurement();
169
}
170
171
/*!
172
\internal
173
Split up iterations into a statistically useful number of blocks.
174
175
Record data in blocks. \c split is the desired number of blocks which is a
176
power of 2 like \c iterationcount. As long as split is below 32 we treat
177
each iteration as a block. When split is greater than 32 \c split becomes
178
a divisor for \c iterationcount. The goal is to reduce overhead from
179
measurements while calculating variance. The default \c split 32 should be
180
sufficient to get stable block-variance, from which the per-iteration
181
variance (estimator) can be computed by dividing by the block size.
182
*/
183
void
QBenchmarkTestMethodData::setBlockSize(
int
split)
184
{
185
measurementBlockSize = iterationCount > split ? iterationCount / split : 1;
186
}
187
188
/*! \internal
189
*/
190
QTest::QBenchmarkIterationController::~QBenchmarkIterationController()
191
{
192
QBenchmarkTestMethodData::current->setResults(QTest::endBenchmarkMeasurement());
193
}
194
195
/*! \internal
196
*/
197
bool
QTest::QBenchmarkIterationController::isDone()
const
noexcept
198
{
199
if
(QBenchmarkTestMethodData::current->runOnce)
200
return
i > 0;
201
return
i >= QTest::iterationCount();
202
}
203
204
/*! \internal
205
*/
206
void
QTest::QBenchmarkIterationController::next()
noexcept
207
{
208
++i;
209
// Record data once per block
210
if
(i % QBenchmarkTestMethodData::current->measurementBlockSize == 0)
211
QBenchmarkGlobalData::current->measurer->updateMeasurement();
212
}
213
214
/*! \internal
215
*/
216
int
QTest::iterationCount()
noexcept
217
{
218
return
QBenchmarkTestMethodData::current->iterationCount;
219
}
220
221
/*! \internal
222
*/
223
void
QTest::beginBenchmarkMeasurement()
224
{
225
QBenchmarkGlobalData::current->measurer->start();
226
// the clock is ticking after the line above, don't add code here.
227
}
228
229
/*! \internal
230
*/
231
QList<QBenchmarkMeasurerBase::Measurement> QTest::endBenchmarkMeasurement()
232
{
233
// the clock is ticking before the line below, don't add code here.
234
return
QBenchmarkGlobalData::current->measurer->stop();
235
}
236
237
/*!
238
Sets the benchmark result for this test function to \a result.
239
240
Use this function if you want to report benchmark results without
241
using the QBENCHMARK macro. Use \a metric to specify how Qt Test
242
should interpret the results.
243
244
The context for the result will be the test function name and any
245
data tag from the _data function. This function can only be called
246
once in each test function, subsequent calls will replace the
247
earlier reported results.
248
249
Note that the -iterations command line argument has no effect
250
on test functions without the QBENCHMARK macro.
251
252
\since 4.7
253
*/
254
void
QTest::setBenchmarkResult(qreal result, QTest::QBenchmarkMetric metric)
255
{
256
QBenchmarkTestMethodData::current->setResult({ result, 0, metric },
false
);
257
}
258
259
QT_END_NAMESPACE
QBenchmarkGlobalData
Definition
qbenchmark_p.h:92
qtbase
src
testlib
qbenchmark.cpp
Generated on
for Qt by
1.18.0