BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslmt_throughputbenchmark

Detailed Description

Outline

Purpose

Provide a performance test harness for multi-threaded components.

Classes

Description

This component defines a mechanism, bslmt::ThroughputBenchmark, that provides performance testing for multi- threaded components. The results are loaded into a bslmt::ThroughputBenchmarkResult object, which provides access to counts of the work done by each thread, thread group, and sample, divided by the number of actual seconds of execution.

Structure of a Test

A test is composed from one or more thread groups, each running one or more threads. Each thread in a thread group executes a thread function, with a simulated work load executing between subsequent calls to the thread function. To provide reliability, the test is executed multiple times. A single execution of a test is referred to as a "sample execution" and its result referred to as a "sample". To support fine tuning of the test, it is possible to provide initialize and cleanup functions for a sample and / or a thread.

Usage

This section illustrates intended use of this component.

Example 1: Test Performance of bsl::queue<int> {#bslmt_throughputbenchmark-example-1-test-performance-of-bsl-queue}

In the following example we test the throughput of a bsl::queue<int> in a multi-threaded environment, where multiple "producer" threads are pushing elements, and multiple "consumer" threads are popping these elements.

First, we define a global queue, a mutex to protect this queue, and a semaphore for a "pop" operation to block on:

bslmt::Mutex myMutex;
Definition bslstl_queue.h:304
Definition bslmt_mutex.h:315
Definition bslmt_semaphore.h:168

Next, we define a counter value we push in:

int counterValue = 0;

Then, we define simple push and pop functions that manipulate this queue:

/// Push an element into `myQueue`, using the specified `threadIndex`.
void myPush(int threadIndex)
{
myQueue.push(1000000 * threadIndex + counterValue++);
mySem.post();
}
/// Pop an element from `myQueue`.
void myPop(int)
{
mySem.wait();
myQueue.pop();
}
void pop()
Definition bslstl_queue.h:790
void push(const value_type &value)
Definition bslstl_queue.h:775
Definition bslmt_lockguard.h:234
void wait()
Definition bslmt_semaphore.h:264
void post()
Atomically increment the count of this semaphore.
Definition bslmt_semaphore.h:246

Next, we define a thread "cleanup" function for the push thread group, which pushes a couple of extra elements to make sure that the pop thread group will not hang on an empty queue:

void myCleanup()
// Cleanup function.
{
for (int i = 0; i < 10; ++i) {
myQueue.push(counterValue++);
mySem.post();
}
}

Then, we create a bslmt::ThroughputBenchmark object and add push and pop thread groups, each with 2 threads and a work load (arithmetic operations to consume an amount of time) of 100:

myPush,
2,
100,
myCleanup);
const int consumerGroupIdx = myBench.addThreadGroup(myPop, 2, 100);
Definition bslmt_throughputbenchmark.h:189
int addThreadGroup(const RunFunction &runFunction, int numThreads, bsls::Types::Int64 busyWorkAmount)

Now, we create a bslmt::ThroughputBenchmarkResult object to contain the result, and call execute to run the benchmark for 500 millseconds 10 times:

myBench.execute(&myResult, 500, 10);
Definition bslmt_throughputbenchmarkresult.h:140
void execute(ThroughputBenchmarkResult *result, int millisecondsPerSample, int numSamples)

Finally, we print the median of the throughput of the consumer thread group.

double median;
myResult.getMedian(&median, consumerGroupIdx);
bsl::cout << "Throughput:" << median << "\n";
void getMedian(double *median, int threadGroupIndex) const