| // 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 "benchmark/benchmark.h" |
| |
| #include <string> |
| #include <vector> |
| |
| #include "arrow/util/decimal.h" |
| #include "arrow/util/logging.h" |
| #include "arrow/util/macros.h" |
| |
| namespace arrow { |
| namespace Decimal { |
| |
| static const std::vector<std::string>& GetValuesAsString() { |
| static const std::vector<std::string> kValues = {"0", |
| "1.23", |
| "12.345e6", |
| "-12.345e-6", |
| "123456789.123456789", |
| "1231234567890.451234567890"}; |
| return kValues; |
| } |
| |
| struct DecimalValueAndScale { |
| Decimal128 decimal; |
| int32_t scale; |
| }; |
| |
| static std::vector<DecimalValueAndScale> GetDecimalValuesAndScales() { |
| const std::vector<std::string>& value_strs = GetValuesAsString(); |
| std::vector<DecimalValueAndScale> result(value_strs.size()); |
| for (size_t i = 0; i < value_strs.size(); ++i) { |
| int32_t precision; |
| ARROW_CHECK_OK(Decimal128::FromString(value_strs[i], &result[i].decimal, |
| &result[i].scale, &precision)); |
| } |
| return result; |
| } |
| |
| static void FromString(benchmark::State& state) { // NOLINT non-const reference |
| const std::vector<std::string>& values = GetValuesAsString(); |
| for (auto _ : state) { |
| for (const auto& value : values) { |
| Decimal128 dec; |
| int32_t scale, precision; |
| benchmark::DoNotOptimize(Decimal128::FromString(value, &dec, &scale, &precision)); |
| } |
| } |
| state.SetItemsProcessed(state.iterations() * values.size()); |
| } |
| |
| static void ToString(benchmark::State& state) { // NOLINT non-const reference |
| static const std::vector<DecimalValueAndScale> values = GetDecimalValuesAndScales(); |
| for (auto _ : state) { |
| for (const DecimalValueAndScale& item : values) { |
| benchmark::DoNotOptimize(item.decimal.ToString(item.scale)); |
| } |
| } |
| state.SetItemsProcessed(state.iterations() * values.size()); |
| } |
| |
| constexpr int32_t kValueSize = 10; |
| |
| static void BinaryCompareOp(benchmark::State& state) { // NOLINT non-const reference |
| std::vector<BasicDecimal128> v1, v2; |
| for (int x = 0; x < kValueSize; x++) { |
| v1.emplace_back(100 + x, 100 + x); |
| v2.emplace_back(200 + x, 200 + x); |
| } |
| for (auto _ : state) { |
| for (int x = 0; x < kValueSize; x += 4) { |
| benchmark::DoNotOptimize(v1[x] == v2[x]); |
| benchmark::DoNotOptimize(v1[x + 1] <= v2[x + 1]); |
| benchmark::DoNotOptimize(v1[x + 2] >= v2[x + 2]); |
| benchmark::DoNotOptimize(v1[x + 3] >= v1[x + 3]); |
| } |
| } |
| state.SetItemsProcessed(state.iterations() * kValueSize); |
| } |
| |
| static void BinaryCompareOpConstant( |
| benchmark::State& state) { // NOLINT non-const reference |
| std::vector<BasicDecimal128> v1; |
| for (int x = 0; x < kValueSize; x++) { |
| v1.emplace_back(100 + x, 100 + x); |
| } |
| BasicDecimal128 constant(313, 212); |
| for (auto _ : state) { |
| for (int x = 0; x < kValueSize; x += 4) { |
| benchmark::DoNotOptimize(v1[x] == constant); |
| benchmark::DoNotOptimize(v1[x + 1] <= constant); |
| benchmark::DoNotOptimize(v1[x + 2] >= constant); |
| benchmark::DoNotOptimize(v1[x + 3] != constant); |
| } |
| } |
| state.SetItemsProcessed(state.iterations() * kValueSize); |
| } |
| |
| static void BinaryMathOpAggregate( |
| benchmark::State& state) { // NOLINT non-const reference |
| std::vector<BasicDecimal128> v; |
| for (int x = 0; x < kValueSize; x++) { |
| v.emplace_back(100 + x, 100 + x); |
| } |
| |
| for (auto _ : state) { |
| BasicDecimal128 result; |
| for (int x = 0; x < 100; x++) { |
| result += v[x]; |
| } |
| benchmark::DoNotOptimize(result); |
| } |
| state.SetItemsProcessed(state.iterations() * kValueSize); |
| } |
| |
| static void BinaryMathOp128(benchmark::State& state) { // NOLINT non-const reference |
| std::vector<BasicDecimal128> v1, v2; |
| for (int x = 0; x < kValueSize; x++) { |
| v1.emplace_back(100 + x, 100 + x); |
| v2.emplace_back(200 + x, 200 + x); |
| } |
| |
| for (auto _ : state) { |
| for (int x = 0; x < kValueSize; x += 5) { |
| benchmark::DoNotOptimize(v1[x] - v2[x]); |
| benchmark::DoNotOptimize(v1[x + 1] + v2[x + 1]); |
| benchmark::DoNotOptimize(v1[x + 2] * v2[x + 2]); |
| benchmark::DoNotOptimize(v1[x + 3] / v2[x + 3]); |
| benchmark::DoNotOptimize(v1[x + 4] % v2[x + 4]); |
| } |
| } |
| state.SetItemsProcessed(state.iterations() * kValueSize); |
| } |
| |
| static void BinaryMathOp256(benchmark::State& state) { // NOLINT non-const reference |
| std::vector<BasicDecimal256> v1, v2; |
| for (uint64_t x = 0; x < kValueSize; x++) { |
| v1.push_back(BasicDecimal256({100 + x, 100 + x, 100 + x, 100 + x})); |
| v2.push_back(BasicDecimal256({200 + x, 200 + x, 200 + x, 200 + x})); |
| } |
| |
| for (auto _ : state) { |
| for (int x = 0; x < kValueSize; x += 5) { |
| benchmark::DoNotOptimize(v1[x + 2] * v2[x + 2]); |
| benchmark::DoNotOptimize(v1[x + 3] / v2[x + 3]); |
| } |
| } |
| state.SetItemsProcessed(state.iterations() * kValueSize); |
| } |
| |
| static void UnaryOp(benchmark::State& state) { // NOLINT non-const reference |
| std::vector<BasicDecimal128> v; |
| for (int x = 0; x < kValueSize; x++) { |
| v.emplace_back(100 + x, 100 + x); |
| } |
| |
| for (auto _ : state) { |
| for (int x = 0; x < kValueSize; x += 2) { |
| benchmark::DoNotOptimize(v[x].Abs()); |
| benchmark::DoNotOptimize(v[x + 1].Negate()); |
| } |
| } |
| state.SetItemsProcessed(state.iterations() * kValueSize); |
| } |
| |
| static void Constants(benchmark::State& state) { // NOLINT non-const reference |
| BasicDecimal128 d1(-546, 123), d2(-123, 456); |
| for (auto _ : state) { |
| benchmark::DoNotOptimize(BasicDecimal128::GetMaxValue() - d1); |
| benchmark::DoNotOptimize(BasicDecimal128::GetScaleMultiplier(3) + d2); |
| } |
| state.SetItemsProcessed(state.iterations() * 2); |
| } |
| |
| static void BinaryBitOp(benchmark::State& state) { // NOLINT non-const reference |
| std::vector<BasicDecimal128> v1, v2; |
| for (int x = 0; x < kValueSize; x++) { |
| v1.emplace_back(100 + x, 100 + x); |
| v2.emplace_back(200 + x, 200 + x); |
| } |
| |
| for (auto _ : state) { |
| for (int x = 0; x < kValueSize; x += 2) { |
| benchmark::DoNotOptimize(v1[x] |= v2[x]); |
| benchmark::DoNotOptimize(v1[x + 1] &= v2[x + 1]); |
| } |
| } |
| state.SetItemsProcessed(state.iterations() * kValueSize); |
| } |
| |
| BENCHMARK(FromString); |
| BENCHMARK(ToString); |
| BENCHMARK(BinaryMathOp128); |
| BENCHMARK(BinaryMathOp256); |
| BENCHMARK(BinaryMathOpAggregate); |
| BENCHMARK(BinaryCompareOp); |
| BENCHMARK(BinaryCompareOpConstant); |
| BENCHMARK(UnaryOp); |
| BENCHMARK(Constants); |
| BENCHMARK(BinaryBitOp); |
| |
| } // namespace Decimal |
| } // namespace arrow |