1 // Copyright The OpenTelemetry Authors
2 // SPDX-License-Identifier: Apache-2.0
4 #include "benchmark/benchmark.h"
14 #include "opentelemetry/sdk/common/circular_buffer.h"
15 #include "test/common/baseline_circular_buffer.h"
16 using opentelemetry::sdk::common::AtomicUniquePtr
;
17 using opentelemetry::sdk::common::CircularBuffer
;
18 using opentelemetry::sdk::common::CircularBufferRange
;
19 using opentelemetry::testing::BaselineCircularBuffer
;
23 static uint64_t ConsumeBufferNumbers(BaselineCircularBuffer
<uint64_t> &buffer
) noexcept
26 buffer
.Consume([&](std::unique_ptr
<uint64_t> &&x
) {
33 static uint64_t ConsumeBufferNumbers(CircularBuffer
<uint64_t> &buffer
) noexcept
36 buffer
.Consume(buffer
.size(),
37 [&](CircularBufferRange
<AtomicUniquePtr
<uint64_t>> &range
) noexcept
{
38 range
.ForEach([&](AtomicUniquePtr
<uint64_t> &ptr
) noexcept
{
47 template <class Buffer
>
48 static void GenerateNumbersForThread(Buffer
&buffer
, int n
, std::atomic
<uint64_t> &sum
) noexcept
50 thread_local
std::mt19937_64 random_number_generator
{std::random_device
{}()};
51 for (int i
= 0; i
< n
; ++i
)
53 auto x
= random_number_generator();
54 std::unique_ptr
<uint64_t> element
{new uint64_t{x
}};
55 if (buffer
.Add(element
))
62 template <class Buffer
>
63 static uint64_t GenerateNumbers(Buffer
&buffer
, int num_threads
, int n
) noexcept
65 std::atomic
<uint64_t> sum
{0};
66 std::vector
<std::thread
> threads(num_threads
);
67 for (auto &thread
: threads
)
69 thread
= std::thread
{GenerateNumbersForThread
<Buffer
>, std::ref(buffer
), n
, std::ref(sum
)};
71 for (auto &thread
: threads
)
78 template <class Buffer
>
79 static void ConsumeNumbers(Buffer
&buffer
, uint64_t &sum
, std::atomic
<bool> &finished
) noexcept
83 sum
+= ConsumeBufferNumbers(buffer
);
85 sum
+= ConsumeBufferNumbers(buffer
);
88 template <class Buffer
>
89 static void RunSimulation(Buffer
&buffer
, int num_threads
, int n
) noexcept
91 std::atomic
<bool> finished
{false};
92 uint64_t consumer_sum
{0};
93 std::thread consumer_thread
{ConsumeNumbers
<Buffer
>, std::ref(buffer
), std::ref(consumer_sum
),
95 uint64_t producer_sum
= GenerateNumbers(buffer
, num_threads
, n
);
97 consumer_thread
.join();
98 if (consumer_sum
!= producer_sum
)
100 std::cerr
<< "Sumulation failed: consumer_sum != producer_sum\n";
105 static void BM_BaselineBuffer(benchmark::State
&state
)
107 const size_t max_elements
= 500;
108 const int num_threads
= static_cast<int>(state
.range(0));
109 const int n
= static_cast<int>(N
/ num_threads
);
110 BaselineCircularBuffer
<uint64_t> buffer
{max_elements
};
113 RunSimulation(buffer
, num_threads
, n
);
117 BENCHMARK(BM_BaselineBuffer
)->Arg(1)->Arg(2)->Arg(4);
119 static void BM_LockFreeBuffer(benchmark::State
&state
)
121 const size_t max_elements
= 500;
122 const int num_threads
= static_cast<int>(state
.range(0));
123 const int n
= static_cast<int>(N
/ num_threads
);
124 CircularBuffer
<uint64_t> buffer
{max_elements
};
127 RunSimulation(buffer
, num_threads
, n
);
131 BENCHMARK(BM_LockFreeBuffer
)->Arg(1)->Arg(2)->Arg(4);