]>
Commit | Line | Data |
---|---|---|
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 | ||
28 | namespace gandiva { | |
29 | ||
30 | using arrow::boolean; | |
31 | using arrow::int32; | |
32 | using arrow::int64; | |
33 | using arrow::utf8; | |
34 | ||
35 | static 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 | ||
66 | static 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 | ||
109 | static 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 | ||
132 | static 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 | ||
159 | static 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 | ||
183 | static 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 | ||
205 | static 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 | ||
227 | static 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 | ||
255 | static 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 | ||
290 | static 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 | ||
324 | static 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 | ||
366 | static 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 | ||
397 | static void DecimalAdd2Fast(benchmark::State& state) { | |
398 | // use lesser precision to test the fast-path | |
399 | DoDecimalAdd2(state, DecimalTypeUtil::kMaxPrecision - 6, 18); | |
400 | } | |
401 | ||
402 | static void DecimalAdd2LeadingZeroes(benchmark::State& state) { | |
403 | // use max precision to test the large-integer-path | |
404 | DoDecimalAdd2(state, DecimalTypeUtil::kMaxPrecision, 6); | |
405 | } | |
406 | ||
407 | static void DecimalAdd2LeadingZeroesWithDiv(benchmark::State& state) { | |
408 | // use max precision to test the large-integer-path | |
409 | DoDecimalAdd2(state, DecimalTypeUtil::kMaxPrecision, 18); | |
410 | } | |
411 | ||
412 | static void DecimalAdd2Large(benchmark::State& state) { | |
413 | // use max precision to test the large-integer-path | |
414 | DoDecimalAdd2(state, DecimalTypeUtil::kMaxPrecision, 18, true); | |
415 | } | |
416 | ||
417 | static void DecimalAdd3Fast(benchmark::State& state) { | |
418 | // use lesser precision to test the fast-path | |
419 | DoDecimalAdd3(state, DecimalTypeUtil::kMaxPrecision - 6, 18); | |
420 | } | |
421 | ||
422 | static void DecimalAdd3LeadingZeroes(benchmark::State& state) { | |
423 | // use max precision to test the large-integer-path | |
424 | DoDecimalAdd3(state, DecimalTypeUtil::kMaxPrecision, 6); | |
425 | } | |
426 | ||
427 | static void DecimalAdd3LeadingZeroesWithDiv(benchmark::State& state) { | |
428 | // use max precision to test the large-integer-path | |
429 | DoDecimalAdd3(state, DecimalTypeUtil::kMaxPrecision, 18); | |
430 | } | |
431 | ||
432 | static void DecimalAdd3Large(benchmark::State& state) { | |
433 | // use max precision to test the large-integer-path | |
434 | DoDecimalAdd3(state, DecimalTypeUtil::kMaxPrecision, 18, true); | |
435 | } | |
436 | ||
437 | BENCHMARK(TimedTestAdd3)->MinTime(1.0)->Unit(benchmark::kMicrosecond); | |
438 | BENCHMARK(TimedTestBigNested)->MinTime(1.0)->Unit(benchmark::kMicrosecond); | |
439 | BENCHMARK(TimedTestExtractYear)->MinTime(1.0)->Unit(benchmark::kMicrosecond); | |
440 | BENCHMARK(TimedTestFilterAdd2)->MinTime(1.0)->Unit(benchmark::kMicrosecond); | |
441 | BENCHMARK(TimedTestFilterLike)->MinTime(1.0)->Unit(benchmark::kMicrosecond); | |
442 | BENCHMARK(TimedTestCastFloatFromString)->MinTime(1.0)->Unit(benchmark::kMicrosecond); | |
443 | BENCHMARK(TimedTestCastIntFromString)->MinTime(1.0)->Unit(benchmark::kMicrosecond); | |
444 | BENCHMARK(TimedTestAllocs)->MinTime(1.0)->Unit(benchmark::kMicrosecond); | |
445 | BENCHMARK(TimedTestMultiOr)->MinTime(1.0)->Unit(benchmark::kMicrosecond); | |
446 | BENCHMARK(TimedTestInExpr)->MinTime(1.0)->Unit(benchmark::kMicrosecond); | |
447 | BENCHMARK(DecimalAdd2Fast)->MinTime(1.0)->Unit(benchmark::kMicrosecond); | |
448 | BENCHMARK(DecimalAdd2LeadingZeroes)->MinTime(1.0)->Unit(benchmark::kMicrosecond); | |
449 | BENCHMARK(DecimalAdd2LeadingZeroesWithDiv)->MinTime(1.0)->Unit(benchmark::kMicrosecond); | |
450 | BENCHMARK(DecimalAdd2Large)->MinTime(1.0)->Unit(benchmark::kMicrosecond); | |
451 | BENCHMARK(DecimalAdd3Fast)->MinTime(1.0)->Unit(benchmark::kMicrosecond); | |
452 | BENCHMARK(DecimalAdd3LeadingZeroes)->MinTime(1.0)->Unit(benchmark::kMicrosecond); | |
453 | BENCHMARK(DecimalAdd3LeadingZeroesWithDiv)->MinTime(1.0)->Unit(benchmark::kMicrosecond); | |
454 | BENCHMARK(DecimalAdd3Large)->MinTime(1.0)->Unit(benchmark::kMicrosecond); | |
455 | ||
456 | } // namespace gandiva |