]> git.proxmox.com Git - ceph.git/blob - ceph/src/arrow/cpp/src/arrow/util/decimal_benchmark.cc
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / cpp / src / arrow / util / decimal_benchmark.cc
1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing,
12 // software distributed under the License is distributed on an
13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, either express or implied. See the License for the
15 // specific language governing permissions and limitations
16 // under the License.
17
18 #include "benchmark/benchmark.h"
19
20 #include <string>
21 #include <vector>
22
23 #include "arrow/util/decimal.h"
24 #include "arrow/util/logging.h"
25 #include "arrow/util/macros.h"
26
27 namespace arrow {
28 namespace Decimal {
29
30 static const std::vector<std::string>& GetValuesAsString() {
31 static const std::vector<std::string> kValues = {"0",
32 "1.23",
33 "12.345e6",
34 "-12.345e-6",
35 "123456789.123456789",
36 "1231234567890.451234567890"};
37 return kValues;
38 }
39
40 struct DecimalValueAndScale {
41 Decimal128 decimal;
42 int32_t scale;
43 };
44
45 static std::vector<DecimalValueAndScale> GetDecimalValuesAndScales() {
46 const std::vector<std::string>& value_strs = GetValuesAsString();
47 std::vector<DecimalValueAndScale> result(value_strs.size());
48 for (size_t i = 0; i < value_strs.size(); ++i) {
49 int32_t precision;
50 ARROW_CHECK_OK(Decimal128::FromString(value_strs[i], &result[i].decimal,
51 &result[i].scale, &precision));
52 }
53 return result;
54 }
55
56 static void FromString(benchmark::State& state) { // NOLINT non-const reference
57 const std::vector<std::string>& values = GetValuesAsString();
58 for (auto _ : state) {
59 for (const auto& value : values) {
60 Decimal128 dec;
61 int32_t scale, precision;
62 benchmark::DoNotOptimize(Decimal128::FromString(value, &dec, &scale, &precision));
63 }
64 }
65 state.SetItemsProcessed(state.iterations() * values.size());
66 }
67
68 static void ToString(benchmark::State& state) { // NOLINT non-const reference
69 static const std::vector<DecimalValueAndScale> values = GetDecimalValuesAndScales();
70 for (auto _ : state) {
71 for (const DecimalValueAndScale& item : values) {
72 benchmark::DoNotOptimize(item.decimal.ToString(item.scale));
73 }
74 }
75 state.SetItemsProcessed(state.iterations() * values.size());
76 }
77
78 constexpr int32_t kValueSize = 10;
79
80 static void BinaryCompareOp(benchmark::State& state) { // NOLINT non-const reference
81 std::vector<BasicDecimal128> v1, v2;
82 for (int x = 0; x < kValueSize; x++) {
83 v1.emplace_back(100 + x, 100 + x);
84 v2.emplace_back(200 + x, 200 + x);
85 }
86 for (auto _ : state) {
87 for (int x = 0; x < kValueSize; x += 4) {
88 benchmark::DoNotOptimize(v1[x] == v2[x]);
89 benchmark::DoNotOptimize(v1[x + 1] <= v2[x + 1]);
90 benchmark::DoNotOptimize(v1[x + 2] >= v2[x + 2]);
91 benchmark::DoNotOptimize(v1[x + 3] >= v1[x + 3]);
92 }
93 }
94 state.SetItemsProcessed(state.iterations() * kValueSize);
95 }
96
97 static void BinaryCompareOpConstant(
98 benchmark::State& state) { // NOLINT non-const reference
99 std::vector<BasicDecimal128> v1;
100 for (int x = 0; x < kValueSize; x++) {
101 v1.emplace_back(100 + x, 100 + x);
102 }
103 BasicDecimal128 constant(313, 212);
104 for (auto _ : state) {
105 for (int x = 0; x < kValueSize; x += 4) {
106 benchmark::DoNotOptimize(v1[x] == constant);
107 benchmark::DoNotOptimize(v1[x + 1] <= constant);
108 benchmark::DoNotOptimize(v1[x + 2] >= constant);
109 benchmark::DoNotOptimize(v1[x + 3] != constant);
110 }
111 }
112 state.SetItemsProcessed(state.iterations() * kValueSize);
113 }
114
115 static void BinaryMathOpAggregate(
116 benchmark::State& state) { // NOLINT non-const reference
117 std::vector<BasicDecimal128> v;
118 for (int x = 0; x < kValueSize; x++) {
119 v.emplace_back(100 + x, 100 + x);
120 }
121
122 for (auto _ : state) {
123 BasicDecimal128 result;
124 for (int x = 0; x < 100; x++) {
125 result += v[x];
126 }
127 benchmark::DoNotOptimize(result);
128 }
129 state.SetItemsProcessed(state.iterations() * kValueSize);
130 }
131
132 static void BinaryMathOpAdd128(benchmark::State& state) { // NOLINT non-const reference
133 std::vector<BasicDecimal128> v1, v2;
134 for (int x = 0; x < kValueSize; x++) {
135 v1.emplace_back(100 + x, 100 + x);
136 v2.emplace_back(200 + x, 200 + x);
137 }
138
139 for (auto _ : state) {
140 for (int x = 0; x < kValueSize; ++x) {
141 benchmark::DoNotOptimize(v1[x] + v2[x]);
142 }
143 }
144 state.SetItemsProcessed(state.iterations() * kValueSize);
145 }
146
147 static void BinaryMathOpMultiply128(
148 benchmark::State& state) { // NOLINT non-const reference
149 std::vector<BasicDecimal128> v1, v2;
150 for (int x = 0; x < kValueSize; x++) {
151 v1.emplace_back(100 + x, 100 + x);
152 v2.emplace_back(200 + x, 200 + x);
153 }
154
155 for (auto _ : state) {
156 for (int x = 0; x < kValueSize; ++x) {
157 benchmark::DoNotOptimize(v1[x] * v2[x]);
158 }
159 }
160 state.SetItemsProcessed(state.iterations() * kValueSize);
161 }
162
163 static void BinaryMathOpDivide128(
164 benchmark::State& state) { // NOLINT non-const reference
165 std::vector<BasicDecimal128> v1, v2;
166 for (int x = 0; x < kValueSize; x++) {
167 v1.emplace_back(100 + x, 100 + x);
168 v2.emplace_back(200 + x, 200 + x);
169 }
170
171 for (auto _ : state) {
172 for (int x = 0; x < kValueSize; ++x) {
173 benchmark::DoNotOptimize(v1[x] / v2[x]);
174 }
175 }
176 state.SetItemsProcessed(state.iterations() * kValueSize);
177 }
178
179 static void BinaryMathOpAdd256(benchmark::State& state) { // NOLINT non-const reference
180 std::vector<BasicDecimal256> v1, v2;
181 for (uint64_t x = 0; x < kValueSize; x++) {
182 v1.push_back(BasicDecimal256({100 + x, 100 + x, 100 + x, 100 + x}));
183 v2.push_back(BasicDecimal256({200 + x, 200 + x, 200 + x, 200 + x}));
184 }
185
186 for (auto _ : state) {
187 for (int x = 0; x < kValueSize; ++x) {
188 benchmark::DoNotOptimize(v1[x] + v2[x]);
189 }
190 }
191 state.SetItemsProcessed(state.iterations() * kValueSize);
192 }
193
194 static void BinaryMathOpMultiply256(
195 benchmark::State& state) { // NOLINT non-const reference
196 std::vector<BasicDecimal256> v1, v2;
197 for (uint64_t x = 0; x < kValueSize; x++) {
198 v1.push_back(BasicDecimal256({100 + x, 100 + x, 100 + x, 100 + x}));
199 v2.push_back(BasicDecimal256({200 + x, 200 + x, 200 + x, 200 + x}));
200 }
201
202 for (auto _ : state) {
203 for (int x = 0; x < kValueSize; ++x) {
204 benchmark::DoNotOptimize(v1[x] * v2[x]);
205 }
206 }
207 state.SetItemsProcessed(state.iterations() * kValueSize);
208 }
209
210 static void BinaryMathOpDivide256(
211 benchmark::State& state) { // NOLINT non-const reference
212 std::vector<BasicDecimal256> v1, v2;
213 for (uint64_t x = 0; x < kValueSize; x++) {
214 v1.push_back(BasicDecimal256({100 + x, 100 + x, 100 + x, 100 + x}));
215 v2.push_back(BasicDecimal256({200 + x, 200 + x, 200 + x, 200 + x}));
216 }
217
218 for (auto _ : state) {
219 for (int x = 0; x < kValueSize; ++x) {
220 benchmark::DoNotOptimize(v1[x] / v2[x]);
221 }
222 }
223 state.SetItemsProcessed(state.iterations() * kValueSize);
224 }
225
226 static void UnaryOp(benchmark::State& state) { // NOLINT non-const reference
227 std::vector<BasicDecimal128> v;
228 for (int x = 0; x < kValueSize; x++) {
229 v.emplace_back(100 + x, 100 + x);
230 }
231
232 for (auto _ : state) {
233 for (int x = 0; x < kValueSize; x += 2) {
234 benchmark::DoNotOptimize(v[x].Abs());
235 benchmark::DoNotOptimize(v[x + 1].Negate());
236 }
237 }
238 state.SetItemsProcessed(state.iterations() * kValueSize);
239 }
240
241 static void Constants(benchmark::State& state) { // NOLINT non-const reference
242 BasicDecimal128 d1(-546, 123), d2(-123, 456);
243 for (auto _ : state) {
244 benchmark::DoNotOptimize(BasicDecimal128::GetMaxValue() - d1);
245 benchmark::DoNotOptimize(BasicDecimal128::GetScaleMultiplier(3) + d2);
246 }
247 state.SetItemsProcessed(state.iterations() * 2);
248 }
249
250 static void BinaryBitOp(benchmark::State& state) { // NOLINT non-const reference
251 std::vector<BasicDecimal128> v1, v2;
252 for (int x = 0; x < kValueSize; x++) {
253 v1.emplace_back(100 + x, 100 + x);
254 v2.emplace_back(200 + x, 200 + x);
255 }
256
257 for (auto _ : state) {
258 for (int x = 0; x < kValueSize; x += 2) {
259 benchmark::DoNotOptimize(v1[x] |= v2[x]);
260 benchmark::DoNotOptimize(v1[x + 1] &= v2[x + 1]);
261 }
262 }
263 state.SetItemsProcessed(state.iterations() * kValueSize);
264 }
265
266 BENCHMARK(FromString);
267 BENCHMARK(ToString);
268 BENCHMARK(BinaryMathOpAdd128);
269 BENCHMARK(BinaryMathOpMultiply128);
270 BENCHMARK(BinaryMathOpDivide128);
271 BENCHMARK(BinaryMathOpAdd256);
272 BENCHMARK(BinaryMathOpMultiply256);
273 BENCHMARK(BinaryMathOpDivide256);
274 BENCHMARK(BinaryMathOpAggregate);
275 BENCHMARK(BinaryCompareOp);
276 BENCHMARK(BinaryCompareOpConstant);
277 BENCHMARK(UnaryOp);
278 BENCHMARK(Constants);
279 BENCHMARK(BinaryBitOp);
280
281 } // namespace Decimal
282 } // namespace arrow