You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

hashtable_debug.h 4.8 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. // Copyright 2018 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. // This library provides APIs to debug the probing behavior of hash tables.
  16. //
  17. // In general, the probing behavior is a black box for users and only the
  18. // side effects can be measured in the form of performance differences.
  19. // These APIs give a glimpse on the actual behavior of the probing algorithms in
  20. // these hashtables given a specified hash function and a set of elements.
  21. //
  22. // The probe count distribution can be used to assess the quality of the hash
  23. // function for that particular hash table. Note that a hash function that
  24. // performs well in one hash table implementation does not necessarily performs
  25. // well in a different one.
  26. //
  27. // This library supports std::unordered_{set,map}, dense_hash_{set,map} and
  28. // absl::{flat,node,string}_hash_{set,map}.
  29. #ifndef ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_
  30. #define ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_
  31. #include <cstddef>
  32. #include <algorithm>
  33. #include <type_traits>
  34. #include <vector>
  35. #include "absl/container/internal/hashtable_debug_hooks.h"
  36. namespace absl
  37. {
  38. ABSL_NAMESPACE_BEGIN
  39. namespace container_internal
  40. {
  41. // Returns the number of probes required to lookup `key`. Returns 0 for a
  42. // search with no collisions. Higher values mean more hash collisions occurred;
  43. // however, the exact meaning of this number varies according to the container
  44. // type.
  45. template<typename C>
  46. size_t GetHashtableDebugNumProbes(
  47. const C& c, const typename C::key_type& key
  48. )
  49. {
  50. return absl::container_internal::hashtable_debug_internal::
  51. HashtableDebugAccess<C>::GetNumProbes(c, key);
  52. }
  53. // Gets a histogram of the number of probes for each elements in the container.
  54. // The sum of all the values in the vector is equal to container.size().
  55. template<typename C>
  56. std::vector<size_t> GetHashtableDebugNumProbesHistogram(const C& container)
  57. {
  58. std::vector<size_t> v;
  59. for (auto it = container.begin(); it != container.end(); ++it)
  60. {
  61. size_t num_probes = GetHashtableDebugNumProbes(
  62. container,
  63. absl::container_internal::hashtable_debug_internal::GetKey<C>(*it, 0)
  64. );
  65. v.resize((std::max)(v.size(), num_probes + 1));
  66. v[num_probes]++;
  67. }
  68. return v;
  69. }
  70. struct HashtableDebugProbeSummary
  71. {
  72. size_t total_elements;
  73. size_t total_num_probes;
  74. double mean;
  75. };
  76. // Gets a summary of the probe count distribution for the elements in the
  77. // container.
  78. template<typename C>
  79. HashtableDebugProbeSummary GetHashtableDebugProbeSummary(const C& container)
  80. {
  81. auto probes = GetHashtableDebugNumProbesHistogram(container);
  82. HashtableDebugProbeSummary summary = {};
  83. for (size_t i = 0; i < probes.size(); ++i)
  84. {
  85. summary.total_elements += probes[i];
  86. summary.total_num_probes += probes[i] * i;
  87. }
  88. summary.mean = 1.0 * summary.total_num_probes / summary.total_elements;
  89. return summary;
  90. }
  91. // Returns the number of bytes requested from the allocator by the container
  92. // and not freed.
  93. template<typename C>
  94. size_t AllocatedByteSize(const C& c)
  95. {
  96. return absl::container_internal::hashtable_debug_internal::
  97. HashtableDebugAccess<C>::AllocatedByteSize(c);
  98. }
  99. // Returns a tight lower bound for AllocatedByteSize(c) where `c` is of type `C`
  100. // and `c.size()` is equal to `num_elements`.
  101. template<typename C>
  102. size_t LowerBoundAllocatedByteSize(size_t num_elements)
  103. {
  104. return absl::container_internal::hashtable_debug_internal::
  105. HashtableDebugAccess<C>::LowerBoundAllocatedByteSize(num_elements);
  106. }
  107. } // namespace container_internal
  108. ABSL_NAMESPACE_END
  109. } // namespace absl
  110. #endif // ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_