BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslmt_throughputbenchmarkresult.h
Go to the documentation of this file.
1/// @file bslmt_throughputbenchmarkresult.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslmt_throughputbenchmarkresult.h -*-C++-*-
8
9#ifndef INCLUDED_BSLMT_THROUGHPUTBENCHMARKRESULT
10#define INCLUDED_BSLMT_THROUGHPUTBENCHMARKRESULT
11
12#include <bsls_ident.h>
13BSLS_IDENT("$Id: $")
14
15/// @defgroup bslmt_throughputbenchmarkresult bslmt_throughputbenchmarkresult
16/// @brief Provide result repository for throughput performance test harness.
17/// @addtogroup bsl
18/// @{
19/// @addtogroup bslmt
20/// @{
21/// @addtogroup bslmt_throughputbenchmarkresult
22/// @{
23///
24/// <h1> Outline </h1>
25/// * <a href="#bslmt_throughputbenchmarkresult-purpose"> Purpose</a>
26/// * <a href="#bslmt_throughputbenchmarkresult-classes"> Classes </a>
27/// * <a href="#bslmt_throughputbenchmarkresult-description"> Description </a>
28/// * <a href="#bslmt_throughputbenchmarkresult-usage"> Usage </a>
29/// * <a href="#bslmt_throughputbenchmarkresult-example-1-calculate-median-and-percentiles"> Example 1: Calculate Median and Percentiles </a>
30///
31/// # Purpose {#bslmt_throughputbenchmarkresult-purpose}
32/// Provide result repository for throughput performance test harness.
33///
34/// # Classes {#bslmt_throughputbenchmarkresult-classes}
35///
36/// - bslmt::ThroughputBenchmarkResult: results for multi-threaded benchmarks
37///
38/// @see bslmt_throughputbenchmark
39///
40/// # Description {#bslmt_throughputbenchmarkresult-description}
41/// This component defines a mechanism,
42/// `bslmt::ThroughputBenchmarkResult`, which represents counts of the work done
43/// by each thread, thread group, and sample, divided by the number of actual
44/// seconds that the sample took to execute. Each specific result can be
45/// retrieved by calling `getValue`, and relevant percentiles can be retrieved
46/// using `getMedian`, `getPercentile`, `getPercentiles`, and
47/// `getThreadPercentiles`.
48///
49/// ## Usage {#bslmt_throughputbenchmarkresult-usage}
50///
51///
52/// This section illustrates intended use of this component.
53///
54/// ### Example 1: Calculate Median and Percentiles {#bslmt_throughputbenchmarkresult-example-1-calculate-median-and-percentiles}
55///
56///
57/// In the following example we populate a `bslmt::ThroughputBenchmarkResult`
58/// object and calculate median and percentiles.
59///
60/// First, we define a vector with thread group sizes:
61/// @code
62/// bsl::vector<int> threadGroupSizes;
63/// threadGroupSizes.resize(2);
64/// threadGroupSizes[0] = 3;
65/// threadGroupSizes[1] = 2;
66/// @endcode
67/// Next, we define a `bslmt::ThroughputBenchmarkResult` with 10 samples and the
68/// previously defined thread group sizes:
69/// @code
70/// bslmt::ThroughputBenchmarkResult myResult(10, threadGroupSizes);
71/// @endcode
72/// Then, we populate the object with throughputs:
73/// @code
74/// for (int tgId = 0; tgId < 2; ++tgId) {
75/// for (int tId = 0; tId < myResult.numThreads(tgId); ++tId) {
76/// for (int sId = 0; sId < 10; ++sId) {
77/// double throughput = static_cast<double>(rand());
78/// myResult.setThroughput(tgId, tId, sId, throughput);
79/// }
80/// }
81/// }
82/// @endcode
83/// Now, we calculate median of the first thread group and print it out:
84/// @code
85/// double median;
86/// myResult.getMedian(&median, 0);
87/// bsl::cout << "Median of first thread group:" << median << "\n";
88/// @endcode
89/// Finally, we calculate percentiles 0, 0.25, 0.5, 0.75, and 1.0 of the first
90/// thread group and print it out:
91/// @code
92/// bsl::vector<double> percentiles(5);
93/// myResult.getPercentiles(&percentiles, 0);
94/// for (int i = 0; i < 5; ++i) {
95/// bsl::cout << "Percentile " << 25 * i << "% is:"
96/// << percentiles[i] << "\n";
97/// }
98/// @endcode
99/// @}
100/** @} */
101/** @} */
102
103/** @addtogroup bsl
104 * @{
105 */
106/** @addtogroup bslmt
107 * @{
108 */
109/** @addtogroup bslmt_throughputbenchmarkresult
110 * @{
111 */
112
113#include <bslscm_version.h>
114
115#include <bslma_allocator.h>
117
119
120#include <bsls_assert.h>
121#include <bsls_keyword.h>
122#include <bsls_types.h>
123
124#include <bsl_vector.h>
125
126
127namespace bslmt {
128
129class ThroughputBenchmarkResult_TestUtil;
130
131 // ===============================
132 // class ThroughputBenchmarkResult
133 // ===============================
134
135/// This class provides support for output of multi-threaded performance
136/// benchmark results. The results are counts of work done during the
137/// benchmark time period divided by the time period.
138///
139/// See @ref bslmt_throughputbenchmarkresult
141
142 public:
143 // PUBLIC TYPES
146
147 private:
148 // DATA
149
150 /// Count of work done, collected from the various threads, and the
151 /// various samples, divided by the actual time period a sample took.
152 /// The inner-most vectors (the `DoubleVector`) are the data for the
153 /// specific threads within a thread group. The middle vector is
154 /// indexed over the thread groups. The outer vector is indexed over
155 /// the samples. That is, to access sample S1, thread group G1, and
156 /// thread index T1 within G1, we refer to
157 /// `d_vecThroughputs[S1][G1][T1]`.
158 bsl::vector<bsl::vector<DoubleVector> > d_vecThroughputs;
159
160 // PRIVATE ACCESSORS
161
162 /// Load into the specified `throughputs` vector a sum of the work done
163 /// by all the threads in the specified `threadGroupIndex`. The size of
164 /// `throughputs` must match the number of samples. The behavior is
165 /// undefined unless `0 <= threadGroupIndex < numThreadGroups` and
166 /// `throughputs->size() == numSamples()`.
167 void getSortedSumThroughputs(bsl::vector<double> *throughputs,
168 int threadGroupIndex) const;
169
170 // FRIENDS
172
173 public:
174 // TRAITS
177
178 // CREATORS
179
180 /// Create an empty `ThroughputBenchmarkResult` object. Optionally
181 /// specify a `basicAllocator` used to supply memory. If
182 /// `basicAllocator` is 0, the currently installed default allocator is
183 /// used. Note that this object has to be initialized before it can be
184 /// used.
185 explicit ThroughputBenchmarkResult(bslma::Allocator *basicAllocator = 0);
186
187 /// Create a `ThroughputBenchmarkResult` object with the specified
188 /// `numSamples` the number of samples in the benchmark, and the
189 /// specified `threadGroupSizes`, the number of threads in each of the
190 /// thread groups. Optionally specify a `basicAllocator` used to supply
191 /// memory. If `basicAllocator` is 0, the currently installed default
192 /// allocator is used. The behavior is undefined unless
193 /// `0 < numSamples`, `0 < threadGroupSizes.size()`, and
194 /// `0 < threadGroupSizes[N]` for all valid `N`.
196 const bsl::vector<int>& threadGroupSizes,
197 bslma::Allocator *basicAllocator = 0);
198
199 /// Create a `ThroughputBenchmarkResult` object having the value of the
200 /// specified `original`. Optionally specify a `basicAllocator` used to
201 /// supply memory. If `basicAllocator` is 0, the currently installed
202 /// default allocator is used.
204 const ThroughputBenchmarkResult& original,
205 bslma::Allocator *basicAllocator = 0);
206
207 /// Create a `ThroughputBenchmarkResult` object having the same value
208 /// and the same allocator as the specified `original` object. The
209 /// value of `original` becomes unspecified but valid, and its allocator
210 /// remains unchanged.
214
215 /// Create a `ThroughputBenchmarkResult` object having the same value as
216 /// the specified `original` object, using the specified
217 /// `basicAllocator` to supply memory. If `basicAllocator` is 0, the
218 /// currently installed default allocator is used. The allocator of
219 /// `original` remains unchanged. If `original` and the newly created
220 /// object have the same allocator then the value of `original` becomes
221 /// unspecified but valid, and no exceptions will be thrown; otherwise
222 /// `original` is unchanged (and an exception may be thrown).
225 bslma::Allocator *basicAllocator);
226
227 /// Destroy this object.
229
230 // MANIPULATORS
231
232 /// Assign to this object the value of the specified `rhs` benchmark
233 /// result, and return a reference providing modifiable access to this
234 /// object.
236
237 /// Assign to this object the value of the specified `rhs` object, and
238 /// return a non-`const` reference to this object. The allocators of
239 /// this object and `rhs` both remain unchanged. If `rhs` and this
240 /// object have the same allocator then the value of `rhs` becomes
241 /// unspecified but valid, and no exceptions will be thrown; otherwise
242 /// `rhs` is unchanged (and an exception may be thrown).
245
246 /// Initialize a default constructed `ThroughputBenchmarkResult` object
247 /// with the specified `numSamples` number of samples in the benchmark,
248 /// and the specified `threadGroupSizes`, the number of threads in each
249 /// of the thread groups. If any data was previously kept, it is lost.
250 /// The behavior is undefined unless `0 < numSamples`,
251 /// `0 < threadGroupSizes.size()`, and `0 < threadGroupSizes[N]` for all
252 /// valid N.
253 void initialize(int numSamples, const bsl::vector<int>& threadGroupSizes);
254
255 /// Set the throughput related to the specified `threadIndex` thread, in
256 /// the specified `threadGroupIndex`, and the specified `sampleIndex` to
257 /// the specified `value`. The behavior is undefined unless
258 /// `0 <= value`, `0 <= threadIndex < numThreads(threadGroupIndex)`,
259 /// `0 <= threadGroupIndex < numThreadGroups()`, and
260 /// `0 <= sampleIndex < numSamples()`.
261 void setThroughput(int threadGroupIndex,
262 int threadIndex,
263 int sampleIndex,
264 double value);
265
266 // ACCESSORS
267
268 // Object state
269
270 /// Return the number of test samples.
271 int numSamples() const;
272
273 /// Return the number of thread groups.
274 int numThreadGroups() const;
275
276 /// Return the number of threads in the specified `threadGroupIdx`. The
277 /// behavior is undefined unless
278 /// `0 <= threadGroupIndex < numThreadGroups()`.
279 int numThreads(int threadGroupIndex) const;
280
281 /// Return the total number of threads.
282 int totalNumThreads() const;
283
284 // Results
285
286 /// Return the throughput of work done on the specified `threadIndex`
287 /// thread, in the specified `threadGroupIndex`, and the specified
288 /// `sampleIndex` sample. The behavior is undefined unless
289 /// `0 <= threadIndex < numThreads(threadGroupIndex)`,
290 /// `0 <= threadGroupIndex < numThreadGroups()`, and
291 /// `0 <= sampleIndex < numSamples()`.
292 double getValue(int threadGroupIndex,
293 int threadIndex,
294 int sampleIndex) const;
295
296 /// Load into the specified `median` the median throughput (count /
297 /// second) of the work done by all the threads in the specified
298 /// `threadGroupIndex`. The behavior is undefined unless
299 /// `0 <= threadGroupIndex < numThreadGroups`.
300 void getMedian(double *median, int threadGroupIndex) const;
301
302 /// Load into the specified `percentile` the specified `percentage`
303 /// throughput (count / second) of the work done by all the threads in
304 /// the specified `threadGroupIndex`. A `percentage` of 0.0 is the
305 /// minimum, and a `percentage` of 1.0 is the maximum. The behavior is
306 /// undefined unless `0 <= threadGroupIndex < numThreadGroups` and
307 /// `0.0 <= percentage <= 1.0`.
308 void getPercentile(double *percentile,
309 double percentage,
310 int threadGroupIndex) const;
311
312 /// Load into the specified `percentiles` vector a uniform breakdown of
313 /// percentage throughput (count / second) of the work done by all the
314 /// threads in the specified `threadGroupIndex`. The size of
315 /// `percentiles` controls how many percentages are provided. For
316 /// example, a size of 5 will return the percentages 0, 0.25, 0.5, 0.75,
317 /// 1. The behavior is undefined unless
318 /// `0 <= threadGroupIndex < numThreadGroups` and
319 /// `2 <= percentiles->size()`.
321 int threadGroupIndex) const;
322
323 /// Load into the specified `percentiles` vector of vectors a uniform
324 /// breakdown of percentage throughput (count / second) of the work done
325 /// on the specified `threadGroupIndex` for each of the threads in it.
326 /// The size of `percentiles` controls how many percentages are
327 /// provided. For example, a size of 5 will return the percentages 0,
328 /// 0.25, 0.5, 0.75, 1. The size of each of the vectors inside `stats`
329 /// must be `numThreads(threadGroupId)`. The behavior is undefined
330 /// unless `0 <= threadGroupId < numThreadGroups`,
331 /// `2 <= percentiles.size()`, and
332 /// `percentiles[N].size() == numThreads(threadGroupIndex)` for all
333 /// N.
335 bsl::vector<bsl::vector<double> > *percentiles,
336 int threadGroupIndex) const;
337
338 // Aspects
339
340 /// Return the allocator used by this object.
342
343};
344
345 // ========================================
346 // class ThroughputBenchmarkResult_TestUtil
347 // ========================================
348
349/// This component-private class provides modifiable access to the
350/// non-public attributes of a `ThroughPutBenchmarkResult` object supplied
351/// on construction, and is provided for use exclusively in the test driver
352/// of this component.
353///
354/// See @ref bslmt_throughputbenchmarkresult
356
357 // DATA
359
360 public:
361 // CREATORS
362
363 /// Create a `ThroughputBenchmarkResult_TestUtil` object to test
364 /// contents of the specified `data`.
367
368 /// Destroy this object.
370
371 // MANIPULATORS
372
373 /// Return a reference providing modifiable access to the
374 /// `d_vecThroughputs` data member of `ThroughputBenchmarkResult`.
376};
377
378// ============================================================================
379// INLINE DEFINITIONS
380// ============================================================================
381
382 // -------------------------------
383 // class ThroughputBenchmarkResult
384 // -------------------------------
385
386// MANIPULATORS
387inline
389 int threadIndex,
390 int sampleIndex,
391 double value)
392{
393 BSLS_ASSERT(0 <= value);
394 BSLS_ASSERT(0 <= threadGroupIndex);
395 BSLS_ASSERT(numThreadGroups() > threadGroupIndex);
396 BSLS_ASSERT(0 <= threadIndex);
397 BSLS_ASSERT(numThreads(threadGroupIndex) > threadIndex);
398 BSLS_ASSERT(0 <= sampleIndex);
399 BSLS_ASSERT(numSamples() > sampleIndex);
400
401 d_vecThroughputs[sampleIndex][threadGroupIndex][threadIndex] = value;
402}
403
404// ACCESSORS
405 // Object state
406inline
408{
409 return static_cast<int>(d_vecThroughputs.size());
410}
411
412inline
414{
415 if (0 == numSamples()) {
416 return 0; // RETURN
417 }
418 return static_cast<int>(d_vecThroughputs[0].size());
419}
420
421inline
422int ThroughputBenchmarkResult::numThreads(int threadGroupIndex) const
423{
424 BSLS_ASSERT(0 <= threadGroupIndex);
425 BSLS_ASSERT(numThreadGroups() > threadGroupIndex);
426
427 return static_cast<int>(d_vecThroughputs[0][threadGroupIndex].size());
428}
429
430inline
432{
433 if (0 == numSamples()) {
434 return 0; // RETURN
435 }
436
437 int nThreadGroups = numThreadGroups();
438 int nThreads = 0;
439 for (int i = 0; i < nThreadGroups; ++i) {
440 nThreads += numThreads(i);
441 }
442 return nThreads;
443}
444
445 // Results
446inline
447double ThroughputBenchmarkResult::getValue(int threadGroupIndex,
448 int threadIndex,
449 int sampleIndex) const
450{
451 BSLS_ASSERT(0 <= threadGroupIndex);
452 BSLS_ASSERT(numThreadGroups() > threadGroupIndex);
453 BSLS_ASSERT(0 <= threadIndex);
454 BSLS_ASSERT(numThreads(threadGroupIndex) > threadIndex);
455 BSLS_ASSERT(0 <= sampleIndex);
456 BSLS_ASSERT(numSamples() > sampleIndex);
457
458 return d_vecThroughputs[sampleIndex][threadGroupIndex][threadIndex];
459}
460
461 // Aspects
462inline
464{
465 return d_vecThroughputs.get_allocator().mechanism();
466}
467
468 // ----------------------------------------
469 // class ThroughputBenchmarkResult_TestUtil
470 // ----------------------------------------
471
472// CREATORS
473inline
479
480// MANIPULATORS
481inline
484{
485 return d_data.d_vecThroughputs;
486}
487
488} // close package namespace
489
490
491#endif
492
493// ----------------------------------------------------------------------------
494// Copyright 2019 Bloomberg Finance L.P.
495//
496// Licensed under the Apache License, Version 2.0 (the "License");
497// you may not use this file except in compliance with the License.
498// You may obtain a copy of the License at
499//
500// http://www.apache.org/licenses/LICENSE-2.0
501//
502// Unless required by applicable law or agreed to in writing, software
503// distributed under the License is distributed on an "AS IS" BASIS,
504// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
505// See the License for the specific language governing permissions and
506// limitations under the License.
507// ----------------------------- END-OF-FILE ----------------------------------
508
509/** @} */
510/** @} */
511/** @} */
Definition bslstl_vector.h:1025
Definition bslma_allocator.h:457
Definition bslmf_movableref.h:751
Definition bslmt_throughputbenchmarkresult.h:355
ThroughputBenchmarkResult_TestUtil(ThroughputBenchmarkResult &data)
Definition bslmt_throughputbenchmarkresult.h:474
bsl::vector< bsl::vector< bsl::vector< double > > > & throughputs()
Definition bslmt_throughputbenchmarkresult.h:483
~ThroughputBenchmarkResult_TestUtil()=default
Destroy this object.
Definition bslmt_throughputbenchmarkresult.h:140
int numThreadGroups() const
Return the number of thread groups.
Definition bslmt_throughputbenchmarkresult.h:413
double getValue(int threadGroupIndex, int threadIndex, int sampleIndex) const
Definition bslmt_throughputbenchmarkresult.h:447
ThroughputBenchmarkResult(bslma::Allocator *basicAllocator=0)
void getPercentile(double *percentile, double percentage, int threadGroupIndex) const
BSLMF_NESTED_TRAIT_DECLARATION(ThroughputBenchmarkResult, bslma::UsesBslmaAllocator)
ThroughputBenchmarkResult(const ThroughputBenchmarkResult &original, bslma::Allocator *basicAllocator=0)
void getMedian(double *median, int threadGroupIndex) const
void setThroughput(int threadGroupIndex, int threadIndex, int sampleIndex, double value)
Definition bslmt_throughputbenchmarkresult.h:388
ThroughputBenchmarkResult(int numSamples, const bsl::vector< int > &threadGroupSizes, bslma::Allocator *basicAllocator=0)
int totalNumThreads() const
Return the total number of threads.
Definition bslmt_throughputbenchmarkresult.h:431
bslma::Allocator * allocator() const
Return the allocator used by this object.
Definition bslmt_throughputbenchmarkresult.h:463
bsls::Types::Int64 Int64
Definition bslmt_throughputbenchmarkresult.h:144
ThroughputBenchmarkResult(bslmf::MovableRef< ThroughputBenchmarkResult > original) BSLS_KEYWORD_NOEXCEPT
void getPercentiles(bsl::vector< double > *percentiles, int threadGroupIndex) const
bsl::vector< double > DoubleVector
Definition bslmt_throughputbenchmarkresult.h:145
int numThreads(int threadGroupIndex) const
Definition bslmt_throughputbenchmarkresult.h:422
~ThroughputBenchmarkResult()=default
Destroy this object.
ThroughputBenchmarkResult & operator=(const ThroughputBenchmarkResult &rhs)
int numSamples() const
Return the number of test samples.
Definition bslmt_throughputbenchmarkresult.h:407
void getThreadPercentiles(bsl::vector< bsl::vector< double > > *percentiles, int threadGroupIndex) const
ThroughputBenchmarkResult(bslmf::MovableRef< ThroughputBenchmarkResult > original, bslma::Allocator *basicAllocator)
void initialize(int numSamples, const bsl::vector< int > &threadGroupSizes)
ThroughputBenchmarkResult & operator=(bslmf::MovableRef< ThroughputBenchmarkResult > rhs)
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:632
Definition bslmt_barrier.h:344
Definition bslma_usesbslmaallocator.h:343
long long Int64
Definition bsls_types.h:132