blob: 0cb82387b145afb31d1b443bd9cd981d0c059684 [file] [log] [blame]
// 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