summaryrefslogtreecommitdiffstats
path: root/src/arrow/cpp/src/gandiva/tests/micro_benchmarks.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/arrow/cpp/src/gandiva/tests/micro_benchmarks.cc')
-rw-r--r--src/arrow/cpp/src/gandiva/tests/micro_benchmarks.cc456
1 files changed, 456 insertions, 0 deletions
diff --git a/src/arrow/cpp/src/gandiva/tests/micro_benchmarks.cc b/src/arrow/cpp/src/gandiva/tests/micro_benchmarks.cc
new file mode 100644
index 000000000..35c77e3dd
--- /dev/null
+++ b/src/arrow/cpp/src/gandiva/tests/micro_benchmarks.cc
@@ -0,0 +1,456 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <stdlib.h>
+#include "arrow/memory_pool.h"
+#include "arrow/status.h"
+#include "benchmark/benchmark.h"
+#include "gandiva/decimal_type_util.h"
+#include "gandiva/projector.h"
+#include "gandiva/tests/test_util.h"
+#include "gandiva/tests/timed_evaluate.h"
+#include "gandiva/tree_expr_builder.h"
+
+namespace gandiva {
+
+using arrow::boolean;
+using arrow::int32;
+using arrow::int64;
+using arrow::utf8;
+
+static void TimedTestAdd3(benchmark::State& state) {
+ // schema for input fields
+ auto field0 = field("f0", int64());
+ auto field1 = field("f1", int64());
+ auto field2 = field("f2", int64());
+ auto schema = arrow::schema({field0, field1, field2});
+ auto pool_ = arrow::default_memory_pool();
+
+ // output field
+ auto field_sum = field("add", int64());
+
+ // Build expression
+ auto part_sum = TreeExprBuilder::MakeFunction(
+ "add", {TreeExprBuilder::MakeField(field1), TreeExprBuilder::MakeField(field2)},
+ int64());
+ auto sum = TreeExprBuilder::MakeFunction(
+ "add", {TreeExprBuilder::MakeField(field0), part_sum}, int64());
+
+ auto sum_expr = TreeExprBuilder::MakeExpression(sum, field_sum);
+
+ std::shared_ptr<Projector> projector;
+ ASSERT_OK(Projector::Make(schema, {sum_expr}, TestConfiguration(), &projector));
+
+ Int64DataGenerator data_generator;
+ ProjectEvaluator evaluator(projector);
+
+ Status status = TimedEvaluate<arrow::Int64Type, int64_t>(
+ schema, evaluator, data_generator, pool_, 1 * MILLION, 16 * THOUSAND, state);
+ ASSERT_OK(status);
+}
+
+static void TimedTestBigNested(benchmark::State& state) {
+ // schema for input fields
+ auto fielda = field("a", int32());
+ auto schema = arrow::schema({fielda});
+ auto pool_ = arrow::default_memory_pool();
+
+ // output fields
+ auto field_result = field("res", int32());
+
+ // build expression.
+ // if (a < 10)
+ // 10
+ // else if (a < 20)
+ // 20
+ // ..
+ // ..
+ // else if (a < 190)
+ // 190
+ // else
+ // 200
+ auto node_a = TreeExprBuilder::MakeField(fielda);
+ auto top_node = TreeExprBuilder::MakeLiteral(200);
+ for (int thresh = 190; thresh > 0; thresh -= 10) {
+ auto literal = TreeExprBuilder::MakeLiteral(thresh);
+ auto condition =
+ TreeExprBuilder::MakeFunction("less_than", {node_a, literal}, boolean());
+ auto if_node = TreeExprBuilder::MakeIf(condition, literal, top_node, int32());
+ top_node = if_node;
+ }
+ auto expr = TreeExprBuilder::MakeExpression(top_node, field_result);
+
+ // Build a projector for the expressions.
+ std::shared_ptr<Projector> projector;
+ ASSERT_OK(Projector::Make(schema, {expr}, TestConfiguration(), &projector));
+
+ BoundedInt32DataGenerator data_generator(250);
+ ProjectEvaluator evaluator(projector);
+
+ Status status = TimedEvaluate<arrow::Int32Type, int32_t>(
+ schema, evaluator, data_generator, pool_, 1 * MILLION, 16 * THOUSAND, state);
+ ASSERT_TRUE(status.ok());
+}
+
+static void TimedTestExtractYear(benchmark::State& state) {
+ // schema for input fields
+ auto field0 = field("f0", arrow::date64());
+ auto schema = arrow::schema({field0});
+ auto pool_ = arrow::default_memory_pool();
+
+ // output field
+ auto field_res = field("res", int64());
+
+ // Build expression
+ auto expr = TreeExprBuilder::MakeExpression("extractYear", {field0}, field_res);
+
+ std::shared_ptr<Projector> projector;
+ ASSERT_OK(Projector::Make(schema, {expr}, TestConfiguration(), &projector));
+
+ Int64DataGenerator data_generator;
+ ProjectEvaluator evaluator(projector);
+
+ Status status = TimedEvaluate<arrow::Date64Type, int64_t>(
+ schema, evaluator, data_generator, pool_, 1 * MILLION, 16 * THOUSAND, state);
+ ASSERT_TRUE(status.ok());
+}
+
+static void TimedTestFilterAdd2(benchmark::State& state) {
+ // schema for input fields
+ auto field0 = field("f0", int64());
+ auto field1 = field("f1", int64());
+ auto field2 = field("f2", int64());
+ auto schema = arrow::schema({field0, field1, field2});
+ auto pool_ = arrow::default_memory_pool();
+
+ // Build expression
+ auto sum = TreeExprBuilder::MakeFunction(
+ "add", {TreeExprBuilder::MakeField(field1), TreeExprBuilder::MakeField(field0)},
+ int64());
+ auto less_than = TreeExprBuilder::MakeFunction(
+ "less_than", {sum, TreeExprBuilder::MakeField(field2)}, boolean());
+ auto condition = TreeExprBuilder::MakeCondition(less_than);
+
+ std::shared_ptr<Filter> filter;
+ ASSERT_OK(Filter::Make(schema, condition, TestConfiguration(), &filter));
+
+ Int64DataGenerator data_generator;
+ FilterEvaluator evaluator(filter);
+
+ Status status = TimedEvaluate<arrow::Int64Type, int64_t>(
+ schema, evaluator, data_generator, pool_, MILLION, 16 * THOUSAND, state);
+ ASSERT_TRUE(status.ok());
+}
+
+static void TimedTestFilterLike(benchmark::State& state) {
+ // schema for input fields
+ auto fielda = field("a", utf8());
+ auto schema = arrow::schema({fielda});
+ auto pool_ = arrow::default_memory_pool();
+
+ // build expression.
+ auto node_a = TreeExprBuilder::MakeField(fielda);
+ auto pattern_node = TreeExprBuilder::MakeStringLiteral("%yellow%");
+ auto like_yellow =
+ TreeExprBuilder::MakeFunction("like", {node_a, pattern_node}, arrow::boolean());
+ auto condition = TreeExprBuilder::MakeCondition(like_yellow);
+
+ std::shared_ptr<Filter> filter;
+ ASSERT_OK(Filter::Make(schema, condition, TestConfiguration(), &filter));
+
+ FastUtf8DataGenerator data_generator(32);
+ FilterEvaluator evaluator(filter);
+
+ Status status = TimedEvaluate<arrow::StringType, std::string>(
+ schema, evaluator, data_generator, pool_, 1 * MILLION, 16 * THOUSAND, state);
+ ASSERT_TRUE(status.ok());
+}
+
+static void TimedTestCastFloatFromString(benchmark::State& state) {
+ auto field_a = field("a", utf8());
+ auto schema = arrow::schema({field_a});
+ auto pool = arrow::default_memory_pool();
+
+ auto field_result = field("res", arrow::float64());
+
+ auto node_a = TreeExprBuilder::MakeField(field_a);
+ auto fn = TreeExprBuilder::MakeFunction("castFLOAT8", {node_a}, arrow::float64());
+ auto expr = TreeExprBuilder::MakeExpression(fn, field_result);
+
+ std::shared_ptr<Projector> projector;
+ ASSERT_OK(Projector::Make(schema, {expr}, TestConfiguration(), &projector));
+
+ Utf8FloatDataGenerator data_generator;
+ ProjectEvaluator evaluator(projector);
+
+ Status status = TimedEvaluate<arrow::StringType, std::string>(
+ schema, evaluator, data_generator, pool, 1 * MILLION, 16 * THOUSAND, state);
+ ASSERT_TRUE(status.ok());
+}
+
+static void TimedTestCastIntFromString(benchmark::State& state) {
+ auto field_a = field("a", utf8());
+ auto schema = arrow::schema({field_a});
+ auto pool = arrow::default_memory_pool();
+
+ auto field_result = field("res", int32());
+
+ auto node_a = TreeExprBuilder::MakeField(field_a);
+ auto fn = TreeExprBuilder::MakeFunction("castINT", {node_a}, int32());
+ auto expr = TreeExprBuilder::MakeExpression(fn, field_result);
+
+ std::shared_ptr<Projector> projector;
+ ASSERT_OK(Projector::Make(schema, {expr}, TestConfiguration(), &projector));
+
+ Utf8IntDataGenerator data_generator;
+ ProjectEvaluator evaluator(projector);
+
+ Status status = TimedEvaluate<arrow::StringType, std::string>(
+ schema, evaluator, data_generator, pool, 1 * MILLION, 16 * THOUSAND, state);
+ ASSERT_TRUE(status.ok());
+}
+
+static void TimedTestAllocs(benchmark::State& state) {
+ // schema for input fields
+ auto field_a = field("a", arrow::utf8());
+ auto schema = arrow::schema({field_a});
+ auto pool_ = arrow::default_memory_pool();
+
+ // output field
+ auto field_res = field("res", int32());
+
+ // Build expression
+ auto node_a = TreeExprBuilder::MakeField(field_a);
+ auto upper = TreeExprBuilder::MakeFunction("upper", {node_a}, utf8());
+ auto length = TreeExprBuilder::MakeFunction("octet_length", {upper}, int32());
+ auto expr = TreeExprBuilder::MakeExpression(length, field_res);
+
+ std::shared_ptr<Projector> projector;
+ ASSERT_OK(Projector::Make(schema, {expr}, TestConfiguration(), &projector));
+
+ FastUtf8DataGenerator data_generator(64);
+ ProjectEvaluator evaluator(projector);
+
+ Status status = TimedEvaluate<arrow::StringType, std::string>(
+ schema, evaluator, data_generator, pool_, 1 * MILLION, 16 * THOUSAND, state);
+ ASSERT_TRUE(status.ok());
+}
+// following two tests are for benchmark optimization of
+// in expr. will be used in follow-up PRs to optimize in expr.
+
+static void TimedTestMultiOr(benchmark::State& state) {
+ // schema for input fields
+ auto fielda = field("a", utf8());
+ auto schema = arrow::schema({fielda});
+ auto pool_ = arrow::default_memory_pool();
+
+ // output fields
+ auto field_result = field("res", boolean());
+
+ // build expression.
+ // booleanOr(a = string1, a = string2, ..)
+ auto node_a = TreeExprBuilder::MakeField(fielda);
+
+ NodeVector boolean_functions;
+ FastUtf8DataGenerator data_generator1(250);
+ for (int thresh = 1; thresh <= 32; thresh++) {
+ auto literal = TreeExprBuilder::MakeStringLiteral(data_generator1.GenerateData());
+ auto condition = TreeExprBuilder::MakeFunction("equal", {node_a, literal}, boolean());
+ boolean_functions.push_back(condition);
+ }
+
+ auto boolean_or = TreeExprBuilder::MakeOr(boolean_functions);
+ auto expr = TreeExprBuilder::MakeExpression(boolean_or, field_result);
+
+ // Build a projector for the expressions.
+ std::shared_ptr<Projector> projector;
+ ASSERT_OK(Projector::Make(schema, {expr}, TestConfiguration(), &projector));
+
+ FastUtf8DataGenerator data_generator(250);
+ ProjectEvaluator evaluator(projector);
+ Status status = TimedEvaluate<arrow::StringType, std::string>(
+ schema, evaluator, data_generator, pool_, 100 * THOUSAND, 16 * THOUSAND, state);
+ ASSERT_OK(status);
+}
+
+static void TimedTestInExpr(benchmark::State& state) {
+ // schema for input fields
+ auto fielda = field("a", utf8());
+ auto schema = arrow::schema({fielda});
+ auto pool_ = arrow::default_memory_pool();
+
+ // output fields
+ auto field_result = field("res", boolean());
+
+ // build expression.
+ // a in (string1, string2, ..)
+ auto node_a = TreeExprBuilder::MakeField(fielda);
+
+ std::unordered_set<std::string> values;
+ FastUtf8DataGenerator data_generator1(250);
+ for (int i = 1; i <= 32; i++) {
+ values.insert(data_generator1.GenerateData());
+ }
+ auto boolean_or = TreeExprBuilder::MakeInExpressionString(node_a, values);
+ auto expr = TreeExprBuilder::MakeExpression(boolean_or, field_result);
+
+ // Build a projector for the expressions.
+ std::shared_ptr<Projector> projector;
+ ASSERT_OK(Projector::Make(schema, {expr}, TestConfiguration(), &projector));
+
+ FastUtf8DataGenerator data_generator(250);
+ ProjectEvaluator evaluator(projector);
+
+ Status status = TimedEvaluate<arrow::StringType, std::string>(
+ schema, evaluator, data_generator, pool_, 100 * THOUSAND, 16 * THOUSAND, state);
+
+ ASSERT_OK(status);
+}
+
+static void DoDecimalAdd3(benchmark::State& state, int32_t precision, int32_t scale,
+ bool large = false) {
+ // schema for input fields
+ auto decimal_type = std::make_shared<arrow::Decimal128Type>(precision, scale);
+ auto field0 = field("f0", decimal_type);
+ auto field1 = field("f1", decimal_type);
+ auto field2 = field("f2", decimal_type);
+ auto schema = arrow::schema({field0, field1, field2});
+
+ Decimal128TypePtr add2_type;
+ auto status = DecimalTypeUtil::GetResultType(DecimalTypeUtil::kOpAdd,
+ {decimal_type, decimal_type}, &add2_type);
+
+ Decimal128TypePtr output_type;
+ status = DecimalTypeUtil::GetResultType(DecimalTypeUtil::kOpAdd,
+ {add2_type, decimal_type}, &output_type);
+
+ // output field
+ auto field_sum = field("add", output_type);
+
+ // Build expression
+ auto part_sum = TreeExprBuilder::MakeFunction(
+ "add", {TreeExprBuilder::MakeField(field1), TreeExprBuilder::MakeField(field2)},
+ add2_type);
+ auto sum = TreeExprBuilder::MakeFunction(
+ "add", {TreeExprBuilder::MakeField(field0), part_sum}, output_type);
+
+ auto sum_expr = TreeExprBuilder::MakeExpression(sum, field_sum);
+
+ std::shared_ptr<Projector> projector;
+ status = Projector::Make(schema, {sum_expr}, TestConfiguration(), &projector);
+ EXPECT_TRUE(status.ok());
+
+ Decimal128DataGenerator data_generator(large);
+ ProjectEvaluator evaluator(projector);
+
+ status = TimedEvaluate<arrow::Decimal128Type, arrow::Decimal128>(
+ schema, evaluator, data_generator, arrow::default_memory_pool(), 1 * MILLION,
+ 16 * THOUSAND, state);
+ ASSERT_OK(status);
+}
+
+static void DoDecimalAdd2(benchmark::State& state, int32_t precision, int32_t scale,
+ bool large = false) {
+ // schema for input fields
+ auto decimal_type = std::make_shared<arrow::Decimal128Type>(precision, scale);
+ auto field0 = field("f0", decimal_type);
+ auto field1 = field("f1", decimal_type);
+ auto schema = arrow::schema({field0, field1});
+
+ Decimal128TypePtr output_type;
+ auto status = DecimalTypeUtil::GetResultType(
+ DecimalTypeUtil::kOpAdd, {decimal_type, decimal_type}, &output_type);
+
+ // output field
+ auto field_sum = field("add", output_type);
+
+ // Build expression
+ auto sum = TreeExprBuilder::MakeExpression("add", {field0, field1}, field_sum);
+
+ std::shared_ptr<Projector> projector;
+ status = Projector::Make(schema, {sum}, TestConfiguration(), &projector);
+ EXPECT_TRUE(status.ok());
+
+ Decimal128DataGenerator data_generator(large);
+ ProjectEvaluator evaluator(projector);
+
+ status = TimedEvaluate<arrow::Decimal128Type, arrow::Decimal128>(
+ schema, evaluator, data_generator, arrow::default_memory_pool(), 1 * MILLION,
+ 16 * THOUSAND, state);
+ ASSERT_OK(status);
+}
+
+static void DecimalAdd2Fast(benchmark::State& state) {
+ // use lesser precision to test the fast-path
+ DoDecimalAdd2(state, DecimalTypeUtil::kMaxPrecision - 6, 18);
+}
+
+static void DecimalAdd2LeadingZeroes(benchmark::State& state) {
+ // use max precision to test the large-integer-path
+ DoDecimalAdd2(state, DecimalTypeUtil::kMaxPrecision, 6);
+}
+
+static void DecimalAdd2LeadingZeroesWithDiv(benchmark::State& state) {
+ // use max precision to test the large-integer-path
+ DoDecimalAdd2(state, DecimalTypeUtil::kMaxPrecision, 18);
+}
+
+static void DecimalAdd2Large(benchmark::State& state) {
+ // use max precision to test the large-integer-path
+ DoDecimalAdd2(state, DecimalTypeUtil::kMaxPrecision, 18, true);
+}
+
+static void DecimalAdd3Fast(benchmark::State& state) {
+ // use lesser precision to test the fast-path
+ DoDecimalAdd3(state, DecimalTypeUtil::kMaxPrecision - 6, 18);
+}
+
+static void DecimalAdd3LeadingZeroes(benchmark::State& state) {
+ // use max precision to test the large-integer-path
+ DoDecimalAdd3(state, DecimalTypeUtil::kMaxPrecision, 6);
+}
+
+static void DecimalAdd3LeadingZeroesWithDiv(benchmark::State& state) {
+ // use max precision to test the large-integer-path
+ DoDecimalAdd3(state, DecimalTypeUtil::kMaxPrecision, 18);
+}
+
+static void DecimalAdd3Large(benchmark::State& state) {
+ // use max precision to test the large-integer-path
+ DoDecimalAdd3(state, DecimalTypeUtil::kMaxPrecision, 18, true);
+}
+
+BENCHMARK(TimedTestAdd3)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
+BENCHMARK(TimedTestBigNested)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
+BENCHMARK(TimedTestExtractYear)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
+BENCHMARK(TimedTestFilterAdd2)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
+BENCHMARK(TimedTestFilterLike)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
+BENCHMARK(TimedTestCastFloatFromString)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
+BENCHMARK(TimedTestCastIntFromString)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
+BENCHMARK(TimedTestAllocs)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
+BENCHMARK(TimedTestMultiOr)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
+BENCHMARK(TimedTestInExpr)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
+BENCHMARK(DecimalAdd2Fast)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
+BENCHMARK(DecimalAdd2LeadingZeroes)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
+BENCHMARK(DecimalAdd2LeadingZeroesWithDiv)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
+BENCHMARK(DecimalAdd2Large)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
+BENCHMARK(DecimalAdd3Fast)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
+BENCHMARK(DecimalAdd3LeadingZeroes)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
+BENCHMARK(DecimalAdd3LeadingZeroesWithDiv)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
+BENCHMARK(DecimalAdd3Large)->MinTime(1.0)->Unit(benchmark::kMicrosecond);
+
+} // namespace gandiva