]> git.proxmox.com Git - ceph.git/blob - ceph/src/jaegertracing/opentelemetry-cpp/sdk/test/common/circular_buffer_benchmark.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / jaegertracing / opentelemetry-cpp / sdk / test / common / circular_buffer_benchmark.cc
1 // Copyright The OpenTelemetry Authors
2 // SPDX-License-Identifier: Apache-2.0
3
4 #include "benchmark/benchmark.h"
5
6 #include <atomic>
7 #include <cstdint>
8 #include <iostream>
9 #include <memory>
10 #include <random>
11 #include <thread>
12 #include <vector>
13
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;
20
21 const int N = 10000;
22
23 static uint64_t ConsumeBufferNumbers(BaselineCircularBuffer<uint64_t> &buffer) noexcept
24 {
25 uint64_t result = 0;
26 buffer.Consume([&](std::unique_ptr<uint64_t> &&x) {
27 result += *x;
28 x.reset();
29 });
30 return result;
31 }
32
33 static uint64_t ConsumeBufferNumbers(CircularBuffer<uint64_t> &buffer) noexcept
34 {
35 uint64_t result = 0;
36 buffer.Consume(buffer.size(),
37 [&](CircularBufferRange<AtomicUniquePtr<uint64_t>> &range) noexcept {
38 range.ForEach([&](AtomicUniquePtr<uint64_t> &ptr) noexcept {
39 result += *ptr;
40 ptr.Reset();
41 return true;
42 });
43 });
44 return result;
45 }
46
47 template <class Buffer>
48 static void GenerateNumbersForThread(Buffer &buffer, int n, std::atomic<uint64_t> &sum) noexcept
49 {
50 thread_local std::mt19937_64 random_number_generator{std::random_device{}()};
51 for (int i = 0; i < n; ++i)
52 {
53 auto x = random_number_generator();
54 std::unique_ptr<uint64_t> element{new uint64_t{x}};
55 if (buffer.Add(element))
56 {
57 sum += x;
58 }
59 }
60 }
61
62 template <class Buffer>
63 static uint64_t GenerateNumbers(Buffer &buffer, int num_threads, int n) noexcept
64 {
65 std::atomic<uint64_t> sum{0};
66 std::vector<std::thread> threads(num_threads);
67 for (auto &thread : threads)
68 {
69 thread = std::thread{GenerateNumbersForThread<Buffer>, std::ref(buffer), n, std::ref(sum)};
70 }
71 for (auto &thread : threads)
72 {
73 thread.join();
74 }
75 return sum;
76 }
77
78 template <class Buffer>
79 static void ConsumeNumbers(Buffer &buffer, uint64_t &sum, std::atomic<bool> &finished) noexcept
80 {
81 while (!finished)
82 {
83 sum += ConsumeBufferNumbers(buffer);
84 }
85 sum += ConsumeBufferNumbers(buffer);
86 }
87
88 template <class Buffer>
89 static void RunSimulation(Buffer &buffer, int num_threads, int n) noexcept
90 {
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),
94 std::ref(finished)};
95 uint64_t producer_sum = GenerateNumbers(buffer, num_threads, n);
96 finished = true;
97 consumer_thread.join();
98 if (consumer_sum != producer_sum)
99 {
100 std::cerr << "Sumulation failed: consumer_sum != producer_sum\n";
101 std::terminate();
102 }
103 }
104
105 static void BM_BaselineBuffer(benchmark::State &state)
106 {
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};
111 for (auto _ : state)
112 {
113 RunSimulation(buffer, num_threads, n);
114 }
115 }
116
117 BENCHMARK(BM_BaselineBuffer)->Arg(1)->Arg(2)->Arg(4);
118
119 static void BM_LockFreeBuffer(benchmark::State &state)
120 {
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};
125 for (auto _ : state)
126 {
127 RunSimulation(buffer, num_threads, n);
128 }
129 }
130
131 BENCHMARK(BM_LockFreeBuffer)->Arg(1)->Arg(2)->Arg(4);
132
133 BENCHMARK_MAIN();