blob: 7bf62c9a7f56c5bad38e35f9591c4306591273fa [file] [log] [blame]
Austin Schuh36244a12019-09-21 17:52:38 -07001// Copyright 2017 The Abseil Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include <cstdint>
16#include <cstring>
17
18#include "benchmark/benchmark.h"
19#include "absl/algorithm/algorithm.h"
20
21namespace {
22
23// The range of sequence sizes to benchmark.
24constexpr int kMinBenchmarkSize = 1024;
25constexpr int kMaxBenchmarkSize = 8 * 1024 * 1024;
26
27// A user-defined type for use in equality benchmarks. Note that we expect
28// std::memcmp to win for this type: libstdc++'s std::equal only defers to
29// memcmp for integral types. This is because it is not straightforward to
30// guarantee that std::memcmp would produce a result "as-if" compared by
31// operator== for other types (example gotchas: NaN floats, structs with
32// padding).
33struct EightBits {
34 explicit EightBits(int /* unused */) : data(0) {}
35 bool operator==(const EightBits& rhs) const { return data == rhs.data; }
36 uint8_t data;
37};
38
39template <typename T>
40void BM_absl_equal_benchmark(benchmark::State& state) {
41 std::vector<T> xs(state.range(0), T(0));
42 std::vector<T> ys = xs;
43 while (state.KeepRunning()) {
44 const bool same = absl::equal(xs.begin(), xs.end(), ys.begin(), ys.end());
45 benchmark::DoNotOptimize(same);
46 }
47}
48
49template <typename T>
50void BM_std_equal_benchmark(benchmark::State& state) {
51 std::vector<T> xs(state.range(0), T(0));
52 std::vector<T> ys = xs;
53 while (state.KeepRunning()) {
54 const bool same = std::equal(xs.begin(), xs.end(), ys.begin());
55 benchmark::DoNotOptimize(same);
56 }
57}
58
59template <typename T>
60void BM_memcmp_benchmark(benchmark::State& state) {
61 std::vector<T> xs(state.range(0), T(0));
62 std::vector<T> ys = xs;
63 while (state.KeepRunning()) {
64 const bool same =
65 std::memcmp(xs.data(), ys.data(), xs.size() * sizeof(T)) == 0;
66 benchmark::DoNotOptimize(same);
67 }
68}
69
70// The expectation is that the compiler should be able to elide the equality
71// comparison altogether for sufficiently simple types.
72template <typename T>
73void BM_absl_equal_self_benchmark(benchmark::State& state) {
74 std::vector<T> xs(state.range(0), T(0));
75 while (state.KeepRunning()) {
76 const bool same = absl::equal(xs.begin(), xs.end(), xs.begin(), xs.end());
77 benchmark::DoNotOptimize(same);
78 }
79}
80
81BENCHMARK_TEMPLATE(BM_absl_equal_benchmark, uint8_t)
82 ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
83BENCHMARK_TEMPLATE(BM_std_equal_benchmark, uint8_t)
84 ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
85BENCHMARK_TEMPLATE(BM_memcmp_benchmark, uint8_t)
86 ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
87BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, uint8_t)
88 ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
89
90BENCHMARK_TEMPLATE(BM_absl_equal_benchmark, uint16_t)
91 ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
92BENCHMARK_TEMPLATE(BM_std_equal_benchmark, uint16_t)
93 ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
94BENCHMARK_TEMPLATE(BM_memcmp_benchmark, uint16_t)
95 ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
96BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, uint16_t)
97 ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
98
99BENCHMARK_TEMPLATE(BM_absl_equal_benchmark, uint32_t)
100 ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
101BENCHMARK_TEMPLATE(BM_std_equal_benchmark, uint32_t)
102 ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
103BENCHMARK_TEMPLATE(BM_memcmp_benchmark, uint32_t)
104 ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
105BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, uint32_t)
106 ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
107
108BENCHMARK_TEMPLATE(BM_absl_equal_benchmark, uint64_t)
109 ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
110BENCHMARK_TEMPLATE(BM_std_equal_benchmark, uint64_t)
111 ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
112BENCHMARK_TEMPLATE(BM_memcmp_benchmark, uint64_t)
113 ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
114BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, uint64_t)
115 ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
116
117BENCHMARK_TEMPLATE(BM_absl_equal_benchmark, EightBits)
118 ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
119BENCHMARK_TEMPLATE(BM_std_equal_benchmark, EightBits)
120 ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
121BENCHMARK_TEMPLATE(BM_memcmp_benchmark, EightBits)
122 ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
123BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, EightBits)
124 ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
125
126} // namespace