aboutsummaryrefslogtreecommitdiff
path: root/third_party/abseil-cpp/absl/hash/hash_benchmark.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/abseil-cpp/absl/hash/hash_benchmark.cc')
-rw-r--r--third_party/abseil-cpp/absl/hash/hash_benchmark.cc254
1 files changed, 0 insertions, 254 deletions
diff --git a/third_party/abseil-cpp/absl/hash/hash_benchmark.cc b/third_party/abseil-cpp/absl/hash/hash_benchmark.cc
deleted file mode 100644
index d498ac29c0..0000000000
--- a/third_party/abseil-cpp/absl/hash/hash_benchmark.cc
+++ /dev/null
@@ -1,254 +0,0 @@
-// Copyright 2018 The Abseil Authors.
-//
-// Licensed 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
-//
-// https://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 <string>
-#include <type_traits>
-#include <typeindex>
-#include <utility>
-#include <vector>
-
-#include "absl/base/attributes.h"
-#include "absl/hash/hash.h"
-#include "absl/random/random.h"
-#include "absl/strings/cord.h"
-#include "absl/strings/cord_test_helpers.h"
-#include "absl/strings/string_view.h"
-#include "benchmark/benchmark.h"
-
-namespace {
-
-using absl::Hash;
-
-template <template <typename> class H, typename T>
-void RunBenchmark(benchmark::State& state, T value) {
- H<T> h;
- for (auto _ : state) {
- benchmark::DoNotOptimize(value);
- benchmark::DoNotOptimize(h(value));
- }
-}
-
-} // namespace
-
-template <typename T>
-using AbslHash = absl::Hash<T>;
-
-class TypeErasedInterface {
- public:
- virtual ~TypeErasedInterface() = default;
-
- template <typename H>
- friend H AbslHashValue(H state, const TypeErasedInterface& wrapper) {
- state = H::combine(std::move(state), std::type_index(typeid(wrapper)));
- wrapper.HashValue(absl::HashState::Create(&state));
- return state;
- }
-
- private:
- virtual void HashValue(absl::HashState state) const = 0;
-};
-
-template <typename T>
-struct TypeErasedAbslHash {
- class Wrapper : public TypeErasedInterface {
- public:
- explicit Wrapper(const T& value) : value_(value) {}
-
- private:
- void HashValue(absl::HashState state) const override {
- absl::HashState::combine(std::move(state), value_);
- }
-
- const T& value_;
- };
-
- size_t operator()(const T& value) {
- return absl::Hash<Wrapper>{}(Wrapper(value));
- }
-};
-
-template <typename FuncType>
-inline FuncType* ODRUseFunction(FuncType* ptr) {
- volatile FuncType* dummy = ptr;
- return dummy;
-}
-
-absl::Cord FlatCord(size_t size) {
- absl::Cord result(std::string(size, 'a'));
- result.Flatten();
- return result;
-}
-
-absl::Cord FragmentedCord(size_t size) {
- const size_t orig_size = size;
- std::vector<std::string> chunks;
- size_t chunk_size = std::max<size_t>(1, size / 10);
- while (size > chunk_size) {
- chunks.push_back(std::string(chunk_size, 'a'));
- size -= chunk_size;
- }
- if (size > 0) {
- chunks.push_back(std::string(size, 'a'));
- }
- absl::Cord result = absl::MakeFragmentedCord(chunks);
- (void) orig_size;
- assert(result.size() == orig_size);
- return result;
-}
-
-// Generates a benchmark and a codegen method for the provided types. The
-// codegen method provides a well known entrypoint for dumping assembly.
-#define MAKE_BENCHMARK(hash, name, ...) \
- namespace { \
- void BM_##hash##_##name(benchmark::State& state) { \
- RunBenchmark<hash>(state, __VA_ARGS__); \
- } \
- BENCHMARK(BM_##hash##_##name); \
- } \
- size_t Codegen##hash##name(const decltype(__VA_ARGS__)& arg); \
- size_t Codegen##hash##name(const decltype(__VA_ARGS__)& arg) { \
- return hash<decltype(__VA_ARGS__)>{}(arg); \
- } \
- bool absl_hash_test_odr_use##hash##name = \
- ODRUseFunction(&Codegen##hash##name);
-
-MAKE_BENCHMARK(AbslHash, Int32, int32_t{});
-MAKE_BENCHMARK(AbslHash, Int64, int64_t{});
-MAKE_BENCHMARK(AbslHash, Double, 1.2);
-MAKE_BENCHMARK(AbslHash, DoubleZero, 0.0);
-MAKE_BENCHMARK(AbslHash, PairInt32Int32, std::pair<int32_t, int32_t>{});
-MAKE_BENCHMARK(AbslHash, PairInt64Int64, std::pair<int64_t, int64_t>{});
-MAKE_BENCHMARK(AbslHash, TupleInt32BoolInt64,
- std::tuple<int32_t, bool, int64_t>{});
-MAKE_BENCHMARK(AbslHash, String_0, std::string());
-MAKE_BENCHMARK(AbslHash, String_10, std::string(10, 'a'));
-MAKE_BENCHMARK(AbslHash, String_30, std::string(30, 'a'));
-MAKE_BENCHMARK(AbslHash, String_90, std::string(90, 'a'));
-MAKE_BENCHMARK(AbslHash, String_200, std::string(200, 'a'));
-MAKE_BENCHMARK(AbslHash, String_5000, std::string(5000, 'a'));
-MAKE_BENCHMARK(AbslHash, Cord_Flat_0, absl::Cord());
-MAKE_BENCHMARK(AbslHash, Cord_Flat_10, FlatCord(10));
-MAKE_BENCHMARK(AbslHash, Cord_Flat_30, FlatCord(30));
-MAKE_BENCHMARK(AbslHash, Cord_Flat_90, FlatCord(90));
-MAKE_BENCHMARK(AbslHash, Cord_Flat_200, FlatCord(200));
-MAKE_BENCHMARK(AbslHash, Cord_Flat_5000, FlatCord(5000));
-MAKE_BENCHMARK(AbslHash, Cord_Fragmented_200, FragmentedCord(200));
-MAKE_BENCHMARK(AbslHash, Cord_Fragmented_5000, FragmentedCord(5000));
-MAKE_BENCHMARK(AbslHash, VectorInt64_10, std::vector<int64_t>(10));
-MAKE_BENCHMARK(AbslHash, VectorInt64_100, std::vector<int64_t>(100));
-MAKE_BENCHMARK(AbslHash, VectorDouble_10, std::vector<double>(10, 1.1));
-MAKE_BENCHMARK(AbslHash, VectorDouble_100, std::vector<double>(100, 1.1));
-MAKE_BENCHMARK(AbslHash, PairStringString_0,
- std::make_pair(std::string(), std::string()));
-MAKE_BENCHMARK(AbslHash, PairStringString_10,
- std::make_pair(std::string(10, 'a'), std::string(10, 'b')));
-MAKE_BENCHMARK(AbslHash, PairStringString_30,
- std::make_pair(std::string(30, 'a'), std::string(30, 'b')));
-MAKE_BENCHMARK(AbslHash, PairStringString_90,
- std::make_pair(std::string(90, 'a'), std::string(90, 'b')));
-MAKE_BENCHMARK(AbslHash, PairStringString_200,
- std::make_pair(std::string(200, 'a'), std::string(200, 'b')));
-MAKE_BENCHMARK(AbslHash, PairStringString_5000,
- std::make_pair(std::string(5000, 'a'), std::string(5000, 'b')));
-
-MAKE_BENCHMARK(TypeErasedAbslHash, Int32, int32_t{});
-MAKE_BENCHMARK(TypeErasedAbslHash, Int64, int64_t{});
-MAKE_BENCHMARK(TypeErasedAbslHash, PairInt32Int32,
- std::pair<int32_t, int32_t>{});
-MAKE_BENCHMARK(TypeErasedAbslHash, PairInt64Int64,
- std::pair<int64_t, int64_t>{});
-MAKE_BENCHMARK(TypeErasedAbslHash, TupleInt32BoolInt64,
- std::tuple<int32_t, bool, int64_t>{});
-MAKE_BENCHMARK(TypeErasedAbslHash, String_0, std::string());
-MAKE_BENCHMARK(TypeErasedAbslHash, String_10, std::string(10, 'a'));
-MAKE_BENCHMARK(TypeErasedAbslHash, String_30, std::string(30, 'a'));
-MAKE_BENCHMARK(TypeErasedAbslHash, String_90, std::string(90, 'a'));
-MAKE_BENCHMARK(TypeErasedAbslHash, String_200, std::string(200, 'a'));
-MAKE_BENCHMARK(TypeErasedAbslHash, String_5000, std::string(5000, 'a'));
-MAKE_BENCHMARK(TypeErasedAbslHash, VectorDouble_10,
- std::vector<double>(10, 1.1));
-MAKE_BENCHMARK(TypeErasedAbslHash, VectorDouble_100,
- std::vector<double>(100, 1.1));
-
-// The latency benchmark attempts to model the speed of the hash function in
-// production. When a hash function is used for hashtable lookups it is rarely
-// used to hash N items in a tight loop nor on constant sized strings. Instead,
-// after hashing there is a potential equality test plus a (usually) large
-// amount of user code. To simulate this effectively we introduce a data
-// dependency between elements we hash by using the hash of the Nth element as
-// the selector of the N+1th element to hash. This isolates the hash function
-// code much like in production. As a bonus we use the hash to generate strings
-// of size [1,N] (instead of fixed N) to disable perfect branch predictions in
-// hash function implementations.
-namespace {
-// 16kb fits in L1 cache of most CPUs we care about. Keeping memory latency low
-// will allow us to attribute most time to CPU which means more accurate
-// measurements.
-static constexpr size_t kEntropySize = 16 << 10;
-static char entropy[kEntropySize + 1024];
-ABSL_ATTRIBUTE_UNUSED static const bool kInitialized = [] {
- absl::BitGen gen;
- static_assert(sizeof(entropy) % sizeof(uint64_t) == 0, "");
- for (int i = 0; i != sizeof(entropy); i += sizeof(uint64_t)) {
- auto rand = absl::Uniform<uint64_t>(gen);
- memcpy(&entropy[i], &rand, sizeof(uint64_t));
- }
- return true;
-}();
-} // namespace
-
-template <class T>
-struct PodRand {
- static_assert(std::is_pod<T>::value, "");
- static_assert(kEntropySize + sizeof(T) < sizeof(entropy), "");
-
- T Get(size_t i) const {
- T v;
- memcpy(&v, &entropy[i % kEntropySize], sizeof(T));
- return v;
- }
-};
-
-template <size_t N>
-struct StringRand {
- static_assert(kEntropySize + N < sizeof(entropy), "");
-
- absl::string_view Get(size_t i) const {
- // This has a small bias towards small numbers. Because max N is ~200 this
- // is very small and prefer to be very fast instead of absolutely accurate.
- // Also we pass N = 2^K+1 so that mod reduces to a bitand.
- size_t s = (i % (N - 1)) + 1;
- return {&entropy[i % kEntropySize], s};
- }
-};
-
-#define MAKE_LATENCY_BENCHMARK(hash, name, ...) \
- namespace { \
- void BM_latency_##hash##_##name(benchmark::State& state) { \
- __VA_ARGS__ r; \
- hash<decltype(r.Get(0))> h; \
- size_t i = 871401241; \
- for (auto _ : state) { \
- benchmark::DoNotOptimize(i = h(r.Get(i))); \
- } \
- } \
- BENCHMARK(BM_latency_##hash##_##name); \
- } // namespace
-
-MAKE_LATENCY_BENCHMARK(AbslHash, Int32, PodRand<int32_t>);
-MAKE_LATENCY_BENCHMARK(AbslHash, Int64, PodRand<int64_t>);
-MAKE_LATENCY_BENCHMARK(AbslHash, String9, StringRand<9>);
-MAKE_LATENCY_BENCHMARK(AbslHash, String33, StringRand<33>);
-MAKE_LATENCY_BENCHMARK(AbslHash, String65, StringRand<65>);
-MAKE_LATENCY_BENCHMARK(AbslHash, String257, StringRand<257>);