abseil-cpp/absl/container/internal/hashtablez_sampler.cc
Go to the documentation of this file.
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 #include "absl/container/internal/hashtablez_sampler.h"
16 
17 #include <atomic>
18 #include <cassert>
19 #include <cmath>
20 #include <functional>
21 #include <limits>
22 
23 #include "absl/base/attributes.h"
24 #include "absl/base/config.h"
25 #include "absl/debugging/stacktrace.h"
26 #include "absl/memory/memory.h"
29 #include "absl/synchronization/mutex.h"
30 #include "absl/utility/utility.h"
31 
32 namespace absl {
34 namespace container_internal {
35 
36 #ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
37 constexpr int HashtablezInfo::kMaxStackDepth;
38 #endif
39 
40 namespace {
41 ABSL_CONST_INIT std::atomic<bool> g_hashtablez_enabled{
42  false
43 };
44 ABSL_CONST_INIT std::atomic<int32_t> g_hashtablez_sample_parameter{1 << 10};
45 std::atomic<HashtablezConfigListener> g_hashtablez_config_listener{nullptr};
46 
47 #if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
49  g_exponential_biased_generator;
50 #endif
51 
52 void TriggerHashtablezConfigListener() {
53  auto* listener = g_hashtablez_config_listener.load(std::memory_order_acquire);
54  if (listener != nullptr) listener();
55 }
56 
57 } // namespace
58 
59 #if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
60 ABSL_PER_THREAD_TLS_KEYWORD SamplingState global_next_sample = {0, 0};
61 #endif // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
62 
64  static auto* sampler = new HashtablezSampler();
65  return *sampler;
66 }
67 
70 
72  size_t inline_element_size_value) {
73  capacity.store(0, std::memory_order_relaxed);
74  size.store(0, std::memory_order_relaxed);
75  num_erases.store(0, std::memory_order_relaxed);
76  num_rehashes.store(0, std::memory_order_relaxed);
77  max_probe_length.store(0, std::memory_order_relaxed);
78  total_probe_length.store(0, std::memory_order_relaxed);
79  hashes_bitwise_or.store(0, std::memory_order_relaxed);
80  hashes_bitwise_and.store(~size_t{}, std::memory_order_relaxed);
81  hashes_bitwise_xor.store(0, std::memory_order_relaxed);
82  max_reserve.store(0, std::memory_order_relaxed);
83 
85  weight = stride;
86  // The inliner makes hardcoded skip_count difficult (especially when combined
87  // with LTO). We use the ability to exclude stacks by regex when encoding
88  // instead.
90  /* skip_count= */ 0);
91  inline_element_size = inline_element_size_value;
92 }
93 
94 static bool ShouldForceSampling() {
95  enum ForceState {
96  kDontForce,
97  kForce,
98  kUninitialized
99  };
100  ABSL_CONST_INIT static std::atomic<ForceState> global_state{
101  kUninitialized};
102  ForceState state = global_state.load(std::memory_order_relaxed);
103  if (ABSL_PREDICT_TRUE(state == kDontForce)) return false;
104 
105  if (state == kUninitialized) {
107  ? kForce
108  : kDontForce;
109  global_state.store(state, std::memory_order_relaxed);
110  }
111  return state == kForce;
112 }
113 
115  size_t inline_element_size) {
117  next_sample.next_sample = 1;
118  const int64_t old_stride = exchange(next_sample.sample_stride, 1);
120  GlobalHashtablezSampler().Register(old_stride, inline_element_size);
121  return result;
122  }
123 
124 #if !defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
125  next_sample = {
128  };
129  return nullptr;
130 #else
131  bool first = next_sample.next_sample < 0;
132 
133  const int64_t next_stride = g_exponential_biased_generator.GetStride(
134  g_hashtablez_sample_parameter.load(std::memory_order_relaxed));
135 
136  next_sample.next_sample = next_stride;
137  const int64_t old_stride = exchange(next_sample.sample_stride, next_stride);
138  // Small values of interval are equivalent to just sampling next time.
139  ABSL_ASSERT(next_stride >= 1);
140 
141  // g_hashtablez_enabled can be dynamically flipped, we need to set a threshold
142  // low enough that we will start sampling in a reasonable time, so we just use
143  // the default sampling rate.
144  if (!g_hashtablez_enabled.load(std::memory_order_relaxed)) return nullptr;
145 
146  // We will only be negative on our first count, so we should just retry in
147  // that case.
148  if (first) {
149  if (ABSL_PREDICT_TRUE(--next_sample.next_sample > 0)) return nullptr;
150  return SampleSlow(next_sample, inline_element_size);
151  }
152 
153  return GlobalHashtablezSampler().Register(old_stride, inline_element_size);
154 #endif
155 }
156 
159 }
160 
162  size_t distance_from_desired) {
163  // SwissTables probe in groups of 16, so scale this to count items probes and
164  // not offset from desired.
165  size_t probe_length = distance_from_desired;
166 #ifdef ABSL_INTERNAL_HAVE_SSE2
167  probe_length /= 16;
168 #else
169  probe_length /= 8;
170 #endif
171 
172  info->hashes_bitwise_and.fetch_and(hash, std::memory_order_relaxed);
173  info->hashes_bitwise_or.fetch_or(hash, std::memory_order_relaxed);
174  info->hashes_bitwise_xor.fetch_xor(hash, std::memory_order_relaxed);
175  info->max_probe_length.store(
176  std::max(info->max_probe_length.load(std::memory_order_relaxed),
177  probe_length),
178  std::memory_order_relaxed);
179  info->total_probe_length.fetch_add(probe_length, std::memory_order_relaxed);
180  info->size.fetch_add(1, std::memory_order_relaxed);
181 }
182 
184  g_hashtablez_config_listener.store(l, std::memory_order_release);
185 }
186 
188  return g_hashtablez_enabled.load(std::memory_order_acquire);
189 }
190 
191 void SetHashtablezEnabled(bool enabled) {
193  TriggerHashtablezConfigListener();
194 }
195 
196 void SetHashtablezEnabledInternal(bool enabled) {
197  g_hashtablez_enabled.store(enabled, std::memory_order_release);
198 }
199 
201  return g_hashtablez_sample_parameter.load(std::memory_order_acquire);
202 }
203 
206  TriggerHashtablezConfigListener();
207 }
208 
210  if (rate > 0) {
211  g_hashtablez_sample_parameter.store(rate, std::memory_order_release);
212  } else {
213  ABSL_RAW_LOG(ERROR, "Invalid hashtablez sample rate: %lld",
214  static_cast<long long>(rate)); // NOLINT(runtime/int)
215  }
216 }
217 
219  return GlobalHashtablezSampler().GetMaxSamples();
220 }
221 
224  TriggerHashtablezConfigListener();
225 }
226 
228  if (max > 0) {
229  GlobalHashtablezSampler().SetMaxSamples(max);
230  } else {
231  ABSL_RAW_LOG(ERROR, "Invalid hashtablez max samples: %lld",
232  static_cast<long long>(max)); // NOLINT(runtime/int)
233  }
234 }
235 
236 } // namespace container_internal
238 } // namespace absl
ABSL_PREDICT_FALSE
#define ABSL_PREDICT_FALSE(x)
Definition: abseil-cpp/absl/base/optimization.h:180
absl::container_internal::SetHashtablezMaxSamples
void SetHashtablezMaxSamples(int32_t max)
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.cc:222
absl::container_internal::HashtablezInfo::stack
void * stack[kMaxStackDepth]
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:94
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
absl::container_internal::HashtablezInfo::HashtablezInfo
HashtablezInfo()
Definition: bloaty/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.cc:63
absl::container_internal::GetHashtablezMaxSamples
int32_t GetHashtablezMaxSamples()
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.cc:218
absl::GetStackTrace
ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackTrace(void **result, int max_depth, int skip_count)
Definition: abseil-cpp/absl/debugging/stacktrace.cc:101
ABSL_CONST_INIT
#define ABSL_CONST_INIT
Definition: abseil-cpp/absl/base/attributes.h:716
absl::container_internal::HashtablezInfo::num_erases
std::atomic< size_t > num_erases
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:77
absl::container_internal::SetHashtablezEnabled
void SetHashtablezEnabled(bool enabled)
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.cc:191
absl::container_internal::HashtablezSampler
::absl::profiling_internal::SampleRecorder< HashtablezInfo > HashtablezSampler
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:265
absl::container_internal::HashtablezSampler::Register
HashtablezInfo * Register()
Definition: bloaty/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.cc:135
absl::container_internal::HashtablezInfo::kMaxStackDepth
static constexpr int kMaxStackDepth
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:91
absl::container_internal::HashtablezInfo::max_reserve
std::atomic< size_t > max_reserve
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:84
absl::container_internal::HashtablezInfo::depth
int32_t depth
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:93
absl::container_internal::IsHashtablezEnabled
bool IsHashtablezEnabled()
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.cc:187
absl::profiling_internal::Sample< HashtablezInfo >::weight
int64_t weight
Definition: sample_recorder.h:49
absl::container_internal::HashtablezSampler::Unregister
void Unregister(HashtablezInfo *sample)
Definition: bloaty/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.cc:153
absl::container_internal::HashtablezSampler
Definition: bloaty/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h:238
absl::container_internal::SampleSlow
HashtablezInfo * SampleSlow(SamplingState &next_sample, size_t inline_element_size)
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.cc:114
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
absl::container_internal::HashtablezInfo::hashes_bitwise_or
std::atomic< size_t > hashes_bitwise_or
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:81
absl::container_internal::SamplingState
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:148
hash
uint64_t hash
Definition: ring_hash.cc:284
sample_recorder.h
absl::container_internal::AbslContainerInternalSampleEverything
bool ABSL_INTERNAL_C_SYMBOL() AbslContainerInternalSampleEverything()
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler_force_weak_definition.cc:25
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition: third_party/abseil-cpp/absl/base/config.h:170
absl::container_internal::HashtablezInfo::hashes_bitwise_and
std::atomic< size_t > hashes_bitwise_and
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:82
absl::container_internal::HashtablezInfo::capacity
std::atomic< size_t > capacity
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:75
int64_t
signed __int64 int64_t
Definition: stdint-msvc2008.h:89
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
absl::container_internal::SamplingState::next_sample
int64_t next_sample
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:149
absl::container_internal::ShouldForceSampling
static bool ShouldForceSampling()
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.cc:94
absl::container_internal::HashtablezInfo::inline_element_size
size_t inline_element_size
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:95
absl::container_internal::HashtablezInfo::num_rehashes
std::atomic< size_t > num_rehashes
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:78
absl::container_internal::HashtablezInfo::create_time
absl::Time create_time
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:92
absl::container_internal::HashtablezInfo::size
std::atomic< size_t > size
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:76
absl::container_internal::HashtablezInfo::~HashtablezInfo
~HashtablezInfo()
ABSL_PER_THREAD_TLS_KEYWORD
#define ABSL_PER_THREAD_TLS_KEYWORD
Definition: abseil-cpp/absl/base/internal/per_thread_tls.h:48
absl::container_internal::HashtablezInfo::max_probe_length
std::atomic< size_t > max_probe_length
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:79
ABSL_INTERNAL_C_SYMBOL
#define ABSL_INTERNAL_C_SYMBOL(x)
Definition: third_party/abseil-cpp/absl/base/config.h:172
absl::container_internal::SetHashtablezMaxSamplesInternal
void SetHashtablezMaxSamplesInternal(int32_t max)
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.cc:227
google::protobuf::ERROR
static const LogLevel ERROR
Definition: bloaty/third_party/protobuf/src/google/protobuf/testing/googletest.h:70
absl::container_internal::SetHashtablezSampleParameter
void SetHashtablezSampleParameter(int32_t rate)
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.cc:204
ABSL_PREDICT_TRUE
#define ABSL_PREDICT_TRUE(x)
Definition: abseil-cpp/absl/base/optimization.h:181
absl::container_internal::GetHashtablezSampleParameter
int32_t GetHashtablezSampleParameter()
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.cc:200
absl::container_internal::SetHashtablezEnabledInternal
void SetHashtablezEnabledInternal(bool enabled)
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.cc:196
absl::container_internal::SetHashtablezConfigListener
void SetHashtablezConfigListener(HashtablezConfigListener l)
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.cc:183
absl::Now
ABSL_NAMESPACE_BEGIN Time Now()
Definition: abseil-cpp/absl/time/clock.cc:39
ABSL_ASSERT
#define ABSL_ASSERT(expr)
Definition: abseil-cpp/absl/base/macros.h:97
absl::container_internal::HashtablezInfo
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:61
absl::container_internal::GlobalHashtablezSampler
HashtablezSampler & GlobalHashtablezSampler()
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.cc:63
absl::container_internal::HashtablezInfo::hashes_bitwise_xor
std::atomic< size_t > hashes_bitwise_xor
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:83
first
StrT first
Definition: cxa_demangle.cpp:4884
state
Definition: bloaty/third_party/zlib/contrib/blast/blast.c:41
absl::container_internal::SamplingState::sample_stride
int64_t sample_stride
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:152
absl::profiling_internal::ExponentialBiased
Definition: abseil-cpp/absl/profiling/internal/exponential_biased.h:74
absl::container_internal::RecordInsertSlow
void RecordInsertSlow(HashtablezInfo *info, size_t hash, size_t distance_from_desired)
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.cc:161
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
absl::container_internal::HashtablezConfigListener
void(*)() HashtablezConfigListener
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:270
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
absl::container_internal::SetHashtablezSampleParameterInternal
void SetHashtablezSampleParameterInternal(int32_t rate)
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.cc:209
int32_t
signed int int32_t
Definition: stdint-msvc2008.h:77
exponential_biased.h
absl::container_internal::HashtablezInfo::PrepareForSampling
void PrepareForSampling() ABSL_EXCLUSIVE_LOCKS_REQUIRED(init_mu)
Definition: bloaty/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.cc:66
ABSL_RAW_LOG
#define ABSL_RAW_LOG(severity,...)
Definition: abseil-cpp/absl/base/internal/raw_logging.h:44
absl::exchange
T exchange(T &obj, U &&new_value)
Definition: abseil-cpp/absl/utility/utility.h:314
absl::container_internal::UnsampleSlow
void UnsampleSlow(HashtablezInfo *info)
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.cc:157
absl::container_internal::HashtablezInfo::total_probe_length
std::atomic< size_t > total_probe_length
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:80


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:01