1*9356374aSAndroid Build Coastguard Worker // Copyright 2018 The Abseil Authors.
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker //
15*9356374aSAndroid Build Coastguard Worker // This library provides APIs to debug the probing behavior of hash tables.
16*9356374aSAndroid Build Coastguard Worker //
17*9356374aSAndroid Build Coastguard Worker // In general, the probing behavior is a black box for users and only the
18*9356374aSAndroid Build Coastguard Worker // side effects can be measured in the form of performance differences.
19*9356374aSAndroid Build Coastguard Worker // These APIs give a glimpse on the actual behavior of the probing algorithms in
20*9356374aSAndroid Build Coastguard Worker // these hashtables given a specified hash function and a set of elements.
21*9356374aSAndroid Build Coastguard Worker //
22*9356374aSAndroid Build Coastguard Worker // The probe count distribution can be used to assess the quality of the hash
23*9356374aSAndroid Build Coastguard Worker // function for that particular hash table. Note that a hash function that
24*9356374aSAndroid Build Coastguard Worker // performs well in one hash table implementation does not necessarily performs
25*9356374aSAndroid Build Coastguard Worker // well in a different one.
26*9356374aSAndroid Build Coastguard Worker //
27*9356374aSAndroid Build Coastguard Worker // This library supports std::unordered_{set,map}, dense_hash_{set,map} and
28*9356374aSAndroid Build Coastguard Worker // absl::{flat,node,string}_hash_{set,map}.
29*9356374aSAndroid Build Coastguard Worker
30*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_
31*9356374aSAndroid Build Coastguard Worker #define ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_
32*9356374aSAndroid Build Coastguard Worker
33*9356374aSAndroid Build Coastguard Worker #include <cstddef>
34*9356374aSAndroid Build Coastguard Worker #include <algorithm>
35*9356374aSAndroid Build Coastguard Worker #include <type_traits>
36*9356374aSAndroid Build Coastguard Worker #include <vector>
37*9356374aSAndroid Build Coastguard Worker
38*9356374aSAndroid Build Coastguard Worker #include "absl/container/internal/hashtable_debug_hooks.h"
39*9356374aSAndroid Build Coastguard Worker
40*9356374aSAndroid Build Coastguard Worker namespace absl {
41*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
42*9356374aSAndroid Build Coastguard Worker namespace container_internal {
43*9356374aSAndroid Build Coastguard Worker
44*9356374aSAndroid Build Coastguard Worker // Returns the number of probes required to lookup `key`. Returns 0 for a
45*9356374aSAndroid Build Coastguard Worker // search with no collisions. Higher values mean more hash collisions occurred;
46*9356374aSAndroid Build Coastguard Worker // however, the exact meaning of this number varies according to the container
47*9356374aSAndroid Build Coastguard Worker // type.
48*9356374aSAndroid Build Coastguard Worker template <typename C>
GetHashtableDebugNumProbes(const C & c,const typename C::key_type & key)49*9356374aSAndroid Build Coastguard Worker size_t GetHashtableDebugNumProbes(
50*9356374aSAndroid Build Coastguard Worker const C& c, const typename C::key_type& key) {
51*9356374aSAndroid Build Coastguard Worker return absl::container_internal::hashtable_debug_internal::
52*9356374aSAndroid Build Coastguard Worker HashtableDebugAccess<C>::GetNumProbes(c, key);
53*9356374aSAndroid Build Coastguard Worker }
54*9356374aSAndroid Build Coastguard Worker
55*9356374aSAndroid Build Coastguard Worker // Gets a histogram of the number of probes for each elements in the container.
56*9356374aSAndroid Build Coastguard Worker // The sum of all the values in the vector is equal to container.size().
57*9356374aSAndroid Build Coastguard Worker template <typename C>
GetHashtableDebugNumProbesHistogram(const C & container)58*9356374aSAndroid Build Coastguard Worker std::vector<size_t> GetHashtableDebugNumProbesHistogram(const C& container) {
59*9356374aSAndroid Build Coastguard Worker std::vector<size_t> v;
60*9356374aSAndroid Build Coastguard Worker for (auto it = container.begin(); it != container.end(); ++it) {
61*9356374aSAndroid Build Coastguard Worker size_t num_probes = GetHashtableDebugNumProbes(
62*9356374aSAndroid Build Coastguard Worker container,
63*9356374aSAndroid Build Coastguard Worker absl::container_internal::hashtable_debug_internal::GetKey<C>(*it, 0));
64*9356374aSAndroid Build Coastguard Worker v.resize((std::max)(v.size(), num_probes + 1));
65*9356374aSAndroid Build Coastguard Worker v[num_probes]++;
66*9356374aSAndroid Build Coastguard Worker }
67*9356374aSAndroid Build Coastguard Worker return v;
68*9356374aSAndroid Build Coastguard Worker }
69*9356374aSAndroid Build Coastguard Worker
70*9356374aSAndroid Build Coastguard Worker struct HashtableDebugProbeSummary {
71*9356374aSAndroid Build Coastguard Worker size_t total_elements;
72*9356374aSAndroid Build Coastguard Worker size_t total_num_probes;
73*9356374aSAndroid Build Coastguard Worker double mean;
74*9356374aSAndroid Build Coastguard Worker };
75*9356374aSAndroid Build Coastguard Worker
76*9356374aSAndroid Build Coastguard Worker // Gets a summary of the probe count distribution for the elements in the
77*9356374aSAndroid Build Coastguard Worker // container.
78*9356374aSAndroid Build Coastguard Worker template <typename C>
GetHashtableDebugProbeSummary(const C & container)79*9356374aSAndroid Build Coastguard Worker HashtableDebugProbeSummary GetHashtableDebugProbeSummary(const C& container) {
80*9356374aSAndroid Build Coastguard Worker auto probes = GetHashtableDebugNumProbesHistogram(container);
81*9356374aSAndroid Build Coastguard Worker HashtableDebugProbeSummary summary = {};
82*9356374aSAndroid Build Coastguard Worker for (size_t i = 0; i < probes.size(); ++i) {
83*9356374aSAndroid Build Coastguard Worker summary.total_elements += probes[i];
84*9356374aSAndroid Build Coastguard Worker summary.total_num_probes += probes[i] * i;
85*9356374aSAndroid Build Coastguard Worker }
86*9356374aSAndroid Build Coastguard Worker summary.mean = 1.0 * summary.total_num_probes / summary.total_elements;
87*9356374aSAndroid Build Coastguard Worker return summary;
88*9356374aSAndroid Build Coastguard Worker }
89*9356374aSAndroid Build Coastguard Worker
90*9356374aSAndroid Build Coastguard Worker // Returns the number of bytes requested from the allocator by the container
91*9356374aSAndroid Build Coastguard Worker // and not freed.
92*9356374aSAndroid Build Coastguard Worker template <typename C>
AllocatedByteSize(const C & c)93*9356374aSAndroid Build Coastguard Worker size_t AllocatedByteSize(const C& c) {
94*9356374aSAndroid Build Coastguard Worker return absl::container_internal::hashtable_debug_internal::
95*9356374aSAndroid Build Coastguard Worker HashtableDebugAccess<C>::AllocatedByteSize(c);
96*9356374aSAndroid Build Coastguard Worker }
97*9356374aSAndroid Build Coastguard Worker
98*9356374aSAndroid Build Coastguard Worker } // namespace container_internal
99*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
100*9356374aSAndroid Build Coastguard Worker } // namespace absl
101*9356374aSAndroid Build Coastguard Worker
102*9356374aSAndroid Build Coastguard Worker #endif // ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_
103