]> git.proxmox.com Git - ceph.git/blame - ceph/src/arrow/cpp/src/gandiva/tests/micro_benchmarks.cc
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / cpp / src / gandiva / tests / micro_benchmarks.cc
CommitLineData
1d09f67e
TL
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 <stdlib.h>
19#include "arrow/memory_pool.h"
20#include "arrow/status.h"
21#include "benchmark/benchmark.h"
22#include "gandiva/decimal_type_util.h"
23#include "gandiva/projector.h"
24#include "gandiva/tests/test_util.h"
25#include "gandiva/tests/timed_evaluate.h"
26#include "gandiva/tree_expr_builder.h"
27
28namespace gandiva {
29
30using arrow::boolean;
31using arrow::int32;
32using arrow::int64;
33using arrow::utf8;
34
35static void TimedTestAdd3(benchmark::State& state) {
36 // schema for input fields
37 auto field0 = field("f0", int64());
38 auto field1 = field("f1", int64());
39 auto field2 = field("f2", int64());
40 auto schema = arrow::schema({field0, field1, field2});
41 auto pool_ = arrow::default_memory_pool();
42
43 // output field
44 auto field_sum = field("add", int64());
45
46 // Build expression
47 auto part_sum = TreeExprBuilder::MakeFunction(
48 "add", {TreeExprBuilder::MakeField(field1), TreeExprBuilder::MakeField(field2)},
49 int64());
50 auto sum = TreeExprBuilder::MakeFunction(
51 "add", {TreeExprBuilder::MakeField(field0), part_sum}, int64());
52
53 auto sum_expr = TreeExprBuilder::MakeExpression(sum, field_sum);
54
55 std::shared_ptr<Projector> projector;
56 ASSERT_OK(Projector::Make(schema, {sum_expr}, TestConfiguration(), &projector));
57
58 Int64DataGenerator data_generator;
59 ProjectEvaluator evaluator(projector);
60
61 Status status = TimedEvaluate<arrow::Int64Type, int64_t>(
62 schema, evaluator, data_generator, pool_, 1 * MILLION, 16 * THOUSAND, state);
63 ASSERT_OK(status);
64}
65
66static void TimedTestBigNested(benchmark::State& state) {
67 // schema for input fields
68 auto fielda = field("a", int32());
69 auto schema = arrow::schema({fielda});
70 auto pool_ = arrow::default_memory_pool();
71
72 // output fields
73 auto field_result = field("res", int32());
74
75 // build expression.
76 // if (a < 10)
77 // 10
78 // else if (a < 20)
79 // 20
80 // ..
81 // ..
82 // else if (a < 190)
83 // 190
84 // else
85 // 200
86 auto node_a = TreeExprBuilder::MakeField(fielda);
87 auto top_node = TreeExprBuilder::MakeLiteral(200);
88 for (int thresh = 190; thresh > 0; thresh -= 10) {
89 auto literal = TreeExprBuilder::MakeLiteral(thresh);
90 auto condition =
91 TreeExprBuilder::MakeFunction("less_than", {node_a, literal}, boolean());
92 auto if_node = TreeExprBuilder::MakeIf(condition, literal, top_node, int32());
93 top_node = if_node;
94 }
95 auto expr = TreeExprBuilder::MakeExpression(top_node, field_result);
96
97 // Build a projector for the expressions.
98 std::shared_ptr<Projector> projector;
99 ASSERT_OK(Projector::Make(schema, {expr}, TestConfiguration(), &projector));
100
101 BoundedInt32DataGenerator data_generator(250);
102 ProjectEvaluator evaluator(projector);
103
104 Status status = TimedEvaluate<arrow::Int32Type, int32_t>(
105 schema, evaluator, data_generator, pool_, 1 * MILLION, 16 * THOUSAND, state);
106 ASSERT_TRUE(status.ok());
107}
108
109static void TimedTestExtractYear(benchmark::State& state) {
110 // schema for input fields
111 auto field0 = field("f0", arrow::date64());
112 auto schema = arrow::schema({field0});
113 auto pool_ = arrow::default_memory_pool();
114
115 // output field
116 auto field_res = field("res", int64());
117
118 // Build expression
119 auto expr = TreeExprBuilder::MakeExpression("extractYear", {field0}, field_res);
120
121 std::shared_ptr<Projector> projector;
122 ASSERT_OK(Projector::Make(schema, {expr}, TestConfiguration(), &projector));
123
124 Int64DataGenerator data_generator;
125 ProjectEvaluator evaluator(projector);
126
127 Status status = TimedEvaluate<arrow::Date64Type, int64_t>(
128 schema, evaluator, data_generator, pool_, 1 * MILLION, 16 * THOUSAND, state);
129 ASSERT_TRUE(status.ok());
130}
131
132static void TimedTestFilterAdd2(benchmark::State& state) {
133 // schema for input fields
134 auto field0 = field("f0", int64());
135 auto field1 = field("f1", int64());
136 auto field2 = field("f2", int64());
137 auto schema = arrow::schema({field0, field1, field2});
138 auto pool_ = arrow::default_memory_pool();
139
140 // Build expression
141 auto sum = TreeExprBuilder::MakeFunction(
142 "add", {TreeExprBuilder::MakeField(field1), TreeExprBuilder::MakeField(field0)},
143 int64());
144 auto less_than = TreeExprBuilder::MakeFunction(
145 "less_than", {sum, TreeExprBuilder::MakeField(field2)}, boolean());
146 auto condition = TreeExprBuilder::MakeCondition(less_than);
147
148 std::shared_ptr<Filter> filter;
149 ASSERT_OK(Filter::Make(schema, condition, TestConfiguration(), &filter));
150
151 Int64DataGenerator data_generator;
152 FilterEvaluator evaluator(filter);
153
154 Status status = TimedEvaluate<arrow::Int64Type, int64_t>(
155 schema, evaluator, data_generator, pool_, MILLION, 16 * THOUSAND, state);
156 ASSERT_TRUE(status.ok());
157}
158
159static void TimedTestFilterLike(benchmark::State& state) {
160 // schema for input fields
161 auto fielda = field("a", utf8());
162 auto schema = arrow::schema({fielda});
163 auto pool_ = arrow::default_memory_pool();
164
165 // build expression.
166 auto node_a = TreeExprBuilder::MakeField(fielda);
167 auto pattern_node = TreeExprBuilder::MakeStringLiteral("%yellow%");
168 auto like_yellow =
169 TreeExprBuilder::MakeFunction("like", {node_a, pattern_node}, arrow::boolean());
170 auto condition = TreeExprBuilder::MakeCondition(like_yellow);
171
172 std::shared_ptr<Filter> filter;
173 ASSERT_OK(Filter::Make(schema, condition, TestConfiguration(), &filter));
174
175 FastUtf8DataGenerator data_generator(32);
176 FilterEvaluator evaluator(filter);
177
178 Status status = TimedEvaluate<arrow::StringType, std::string>(
179 schema, evaluator, data_generator, pool_, 1 * MILLION, 16 * THOUSAND, state);
180 ASSERT_TRUE(status.ok());
181}
182
183static void TimedTestCastFloatFromString(benchmark::State& state) {
184 auto field_a = field("a", utf8());
185 auto schema = arrow::schema({field_a});
186 auto pool = arrow::default_memory_pool();
187
188 auto field_result = field("res", arrow::float64());
189
190 auto node_a = TreeExprBuilder::MakeField(field_a);
191 auto fn = TreeExprBuilder::MakeFunction("castFLOAT8", {node_a}, arrow::float64());
192 auto expr = TreeExprBuilder::MakeExpression(fn, field_result);
193
194 std::shared_ptr<Projector> projector;
195 ASSERT_OK(Projector::Make(schema, {expr}, TestConfiguration(), &projector));
196
197 Utf8FloatDataGenerator data_generator;
198 ProjectEvaluator evaluator(projector);
199
200 Status status = TimedEvaluate<arrow::StringType, std::string>(
201 schema, evaluator, data_generator, pool, 1 * MILLION, 16 * THOUSAND, state);
202 ASSERT_TRUE(status.ok());
203}
204
205static void TimedTestCastIntFromString(benchmark::State& state) {
206 auto field_a = field("a", utf8());
207 auto schema = arrow::schema({field_a});
208 auto pool = arrow::default_memory_pool();
209
210 auto field_result = field("res", int32());
211
212 auto node_a = TreeExprBuilder::MakeField(field_a);
213 auto fn = TreeExprBuilder::MakeFunction("castINT", {node_a}, int32());
214 auto expr = TreeExprBuilder::MakeExpression(fn, field_result);
215
216 std::shared_ptr<Projector> projector;
217 ASSERT_OK(Projector::Make(schema, {expr}, TestConfiguration(), &projector));
218
219 Utf8IntDataGenerator data_generator;
220 ProjectEvaluator evaluator(projector);
221
222 Status status = TimedEvaluate<arrow::StringType, std::string>(
223 schema, evaluator, data_generator, pool, 1 * MILLION, 16 * THOUSAND, state);
224 ASSERT_TRUE(status.ok());
225}
226
227static void TimedTestAllocs(benchmark::State& state) {
228 // schema for input fields
229 auto field_a = field("a", arrow::utf8());
230 auto schema = arrow::schema({field_a});
231 auto pool_ = arrow::default_memory_pool();
232
233 // output field
234 auto field_res = field("res", int32());
235
236 // Build expression
237 auto node_a = TreeExprBuilder::MakeField(field_a);
238 auto upper = TreeExprBuilder::MakeFunction("upper", {node_a}, utf8());
239 auto length = TreeExprBuilder::MakeFunction("octet_length", {upper}, int32());
240 auto expr = TreeExprBuilder::MakeExpression(length, field_res);
241
242 std::shared_ptr<Projector> projector;
243 ASSERT_OK(Projector::Make(schema, {expr}, TestConfiguration(), &projector));
244
245 FastUtf8DataGenerator data_generator(64);
246 ProjectEvaluator evaluator(projector);
247
248 Status status = TimedEvaluate<arrow::StringType, std::string>(
249 schema, evaluator, data_generator, pool_, 1 * MILLION, 16 * THOUSAND, state);
250 ASSERT_TRUE(status.ok());
251}
252// following two tests are for benchmark optimization of
253// in expr. will be used in follow-up PRs to optimize in expr.
254
255static void TimedTestMultiOr(benchmark::State& state) {
256 // schema for input fields
257 auto fielda = field("a", utf8());
258 auto schema = arrow::schema({fielda});
259 auto pool_ = arrow::default_memory_pool();
260
261 // output fields
262 auto field_result = field("res", boolean());
263
264 // build expression.
265 // booleanOr(a = string1, a = string2, ..)
266 auto node_a = TreeExprBuilder::MakeField(fielda);
267
268 NodeVector boolean_functions;
269 FastUtf8DataGenerator data_generator1(250);
270 for (int thresh = 1; thresh <= 32; thresh++) {
271 auto literal = TreeExprBuilder::MakeStringLiteral(data_generator1.GenerateData());
272 auto condition = TreeExprBuilder::MakeFunction("equal", {node_a, literal}, boolean());
273 boolean_functions.push_back(condition);
274 }
275
276 auto boolean_or = TreeExprBuilder::MakeOr(boolean_functions);
277 auto expr = TreeExprBuilder::MakeExpression(boolean_or, field_result);
278
279 // Build a projector for the expressions.
280 std::shared_ptr<Projector> projector;
281 ASSERT_OK(Projector::Make(schema, {expr}, TestConfiguration(), &projector));
282
283 FastUtf8DataGenerator data_generator(250);
284 ProjectEvaluator evaluator(projector);
285 Status status = TimedEvaluate<arrow::StringType, std::string>(
286 schema, evaluator, data_generator, pool_, 100 * THOUSAND, 16 * THOUSAND, state);
287 ASSERT_OK(status);
288}
289
290static void TimedTestInExpr(benchmark::State& state) {
291 // schema for input fields
292 auto fielda = field("a", utf8());
293 auto schema = arrow::schema({fielda});
294 auto pool_ = arrow::default_memory_pool();
295
296 // output fields
297 auto field_result = field("res", boolean());
298
299 // build expression.
300 // a in (string1, string2, ..)
301 auto node_a = TreeExprBuilder::MakeField(fielda);
302
303 std::unordered_set<std::string> values;
304 FastUtf8DataGenerator data_generator1(250);
305 for (int i = 1; i <= 32; i++) {
306 values.insert(data_generator1.GenerateData());
307 }
308 auto boolean_or = TreeExprBuilder::MakeInExpressionString(node_a, values);
309 auto expr = TreeExprBuilder::MakeExpression(boolean_or, field_result);
310
311 // Build a projector for the expressions.
312 std::shared_ptr<Projector> projector;
313 ASSERT_OK(Projector::Make(schema, {expr}, TestConfiguration(), &projector));
314
315 FastUtf8DataGenerator data_generator(250);
316 ProjectEvaluator evaluator(projector);
317
318 Status status = TimedEvaluate<arrow::StringType, std::string>(
319 schema, evaluator, data_generator, pool_, 100 * THOUSAND, 16 * THOUSAND, state);
320
321 ASSERT_OK(status);
322}
323
324static void DoDecimalAdd3(benchmark::State& state, int32_t precision, int32_t scale,
325 bool large = false) {
326 // schema for input fields
327 auto decimal_type = std::make_shared<arrow::Decimal128Type>(precision, scale);
328 auto field0 = field("f0", decimal_type);
329 auto field1 = field("f1", decimal_type);
330 auto field2 = field("f2", decimal_type);
331 auto schema = arrow::schema({field0, field1, field2});
332
333 Decimal128TypePtr add2_type;
334 auto status = DecimalTypeUtil::GetResultType(DecimalTypeUtil::kOpAdd,
335 {decimal_type, decimal_type}, &add2_type);
336
337 Decimal128TypePtr output_type;
338 status = DecimalTypeUtil::GetResultType(DecimalTypeUtil::kOpAdd,
339 {add2_type, decimal_type}, &output_type);
340
341 // output field
342 auto field_sum = field("add", output_type);
343
344 // Build expression
345 auto part_sum = TreeExprBuilder::MakeFunction(
346 "add", {TreeExprBuilder::MakeField(field1), TreeExprBuilder::MakeField(field2)},
347 add2_type);
348 auto sum = TreeExprBuilder::MakeFunction(
349 "add", {TreeExprBuilder::MakeField(field0), part_sum}, output_type);
350
351 auto sum_expr = TreeExprBuilder::MakeExpression(sum, field_sum);
352
353 std::shared_ptr<Projector> projector;
354 status = Projector::Make(schema, {sum_expr}, TestConfiguration(), &projector);
355 EXPECT_TRUE(status.ok());
356
357 Decimal128DataGenerator data_generator(large);
358 ProjectEvaluator evaluator(projector);
359
360 status = TimedEvaluate<arrow::Decimal128Type, arrow::Decimal128>(
361 schema, evaluator, data_generator, arrow::default_memory_pool(), 1 * MILLION,
362 16 * THOUSAND, state);
363 ASSERT_OK(status);
364}
365
366static void DoDecimalAdd2(benchmark::State& state, int32_t precision, int32_t scale,
367 bool large = false) {
368 // schema for input fields
369 auto decimal_type = std::make_shared<arrow::Decimal128Type>(precision, scale);
370 auto field0 = field("f0", decimal_type);
371 auto field1 = field("f1", decimal_type);
372 auto schema = arrow::schema({field0, field1});
373
374 Decimal128TypePtr output_type;
375 auto status = DecimalTypeUtil::GetResultType(
376 DecimalTypeUtil::kOpAdd, {decimal_type, decimal_type}, &output_type);
377
378 // output field
379 auto field_sum = field("add", output_type);
380
381 // Build expression
382 auto sum = TreeExprBuilder::MakeExpression("add", {field0, field1}, field_sum);
383
384 std::shared_ptr<Projector> projector;
385 status = Projector::Make(schema, {sum}, TestConfiguration(), &projector);
386 EXPECT_TRUE(status.ok());
387
388 Decimal128DataGenerator data_generator(large);
389 ProjectEvaluator evaluator(projector);
390
391 status = TimedEvaluate<arrow::Decimal128Type, arrow::Decimal128>(
392 schema, evaluator, data_generator, arrow::default_memory_pool(), 1 * MILLION,
393 16 * THOUSAND, state);
394 ASSERT_OK(status);
395}
396
397static void DecimalAdd2Fast(benchmark::State& state) {
398 // use lesser precision to test the fast-path
399 DoDecimalAdd2(state, DecimalTypeUtil::kMaxPrecision - 6, 18);
400}
401
402static void DecimalAdd2LeadingZeroes(benchmark::State& state) {
403 // use max precision to test the large-integer-path
404 DoDecimalAdd2(state, DecimalTypeUtil::kMaxPrecision, 6);
405}
406
407static void DecimalAdd2LeadingZeroesWithDiv(benchmark::State& state) {
408 // use max precision to test the large-integer-path
409 DoDecimalAdd2(state, DecimalTypeUtil::kMaxPrecision, 18);
410}
411
412static void DecimalAdd2Large(benchmark::State& state) {
413 // use max precision to test the large-integer-path
414 DoDecimalAdd2(state, DecimalTypeUtil::kMaxPrecision, 18, true);
415}
416
417static void DecimalAdd3Fast(benchmark::State& state) {
418 // use lesser precision to test the fast-path
419 DoDecimalAdd3(state, DecimalTypeUtil::kMaxPrecision - 6, 18);
420}
421
422static void DecimalAdd3LeadingZeroes(benchmark::State& state) {
423 // use max precision to test the large-integer-path
424 DoDecimalAdd3(state, DecimalTypeUtil::kMaxPrecision, 6);
425}
426
427static void DecimalAdd3LeadingZeroesWithDiv(benchmark::State& state) {
428 // use max precision to test the large-integer-path
429 DoDecimalAdd3(state, DecimalTypeUtil::kMaxPrecision, 18);
430}
431
432static void DecimalAdd3Large(benchmark::State& state) {
433 // use max precision to test the large-integer-path
434 DoDecimalAdd3(state, DecimalTypeUtil::kMaxPrecision, 18, true);
435}
436
437BENCHMARK(TimedTestAdd3)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
438BENCHMARK(TimedTestBigNested)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
439BENCHMARK(TimedTestExtractYear)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
440BENCHMARK(TimedTestFilterAdd2)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
441BENCHMARK(TimedTestFilterLike)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
442BENCHMARK(TimedTestCastFloatFromString)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
443BENCHMARK(TimedTestCastIntFromString)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
444BENCHMARK(TimedTestAllocs)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
445BENCHMARK(TimedTestMultiOr)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
446BENCHMARK(TimedTestInExpr)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
447BENCHMARK(DecimalAdd2Fast)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
448BENCHMARK(DecimalAdd2LeadingZeroes)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
449BENCHMARK(DecimalAdd2LeadingZeroesWithDiv)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
450BENCHMARK(DecimalAdd2Large)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
451BENCHMARK(DecimalAdd3Fast)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
452BENCHMARK(DecimalAdd3LeadingZeroes)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
453BENCHMARK(DecimalAdd3LeadingZeroesWithDiv)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
454BENCHMARK(DecimalAdd3Large)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
455
456} // namespace gandiva