hashtable_debug.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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. // y_absl::{flat,node,string}_hash_{set,map}.
  29. #ifndef Y_ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_
  30. #define Y_ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_
  31. #include <cstddef>
  32. #include <algorithm>
  33. #include <type_traits>
  34. #include <vector>
  35. #include "y_absl/container/internal/hashtable_debug_hooks.h"
  36. namespace y_absl {
  37. Y_ABSL_NAMESPACE_BEGIN
  38. namespace container_internal {
  39. // Returns the number of probes required to lookup `key`. Returns 0 for a
  40. // search with no collisions. Higher values mean more hash collisions occurred;
  41. // however, the exact meaning of this number varies according to the container
  42. // type.
  43. template <typename C>
  44. size_t GetHashtableDebugNumProbes(
  45. const C& c, const typename C::key_type& key) {
  46. return y_absl::container_internal::hashtable_debug_internal::
  47. HashtableDebugAccess<C>::GetNumProbes(c, key);
  48. }
  49. // Gets a histogram of the number of probes for each elements in the container.
  50. // The sum of all the values in the vector is equal to container.size().
  51. template <typename C>
  52. std::vector<size_t> GetHashtableDebugNumProbesHistogram(const C& container) {
  53. std::vector<size_t> v;
  54. for (auto it = container.begin(); it != container.end(); ++it) {
  55. size_t num_probes = GetHashtableDebugNumProbes(
  56. container,
  57. y_absl::container_internal::hashtable_debug_internal::GetKey<C>(*it, 0));
  58. v.resize((std::max)(v.size(), num_probes + 1));
  59. v[num_probes]++;
  60. }
  61. return v;
  62. }
  63. struct HashtableDebugProbeSummary {
  64. size_t total_elements;
  65. size_t total_num_probes;
  66. double mean;
  67. };
  68. // Gets a summary of the probe count distribution for the elements in the
  69. // container.
  70. template <typename C>
  71. HashtableDebugProbeSummary GetHashtableDebugProbeSummary(const C& container) {
  72. auto probes = GetHashtableDebugNumProbesHistogram(container);
  73. HashtableDebugProbeSummary summary = {};
  74. for (size_t i = 0; i < probes.size(); ++i) {
  75. summary.total_elements += probes[i];
  76. summary.total_num_probes += probes[i] * i;
  77. }
  78. summary.mean = 1.0 * summary.total_num_probes / summary.total_elements;
  79. return summary;
  80. }
  81. // Returns the number of bytes requested from the allocator by the container
  82. // and not freed.
  83. template <typename C>
  84. size_t AllocatedByteSize(const C& c) {
  85. return y_absl::container_internal::hashtable_debug_internal::
  86. HashtableDebugAccess<C>::AllocatedByteSize(c);
  87. }
  88. } // namespace container_internal
  89. Y_ABSL_NAMESPACE_END
  90. } // namespace y_absl
  91. #endif // Y_ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_