File indexing completed on 2025-01-18 09:27:11
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 #ifndef ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_
0040 #define ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_
0041
0042 #include <atomic>
0043 #include <cstddef>
0044 #include <cstdint>
0045 #include <functional>
0046 #include <memory>
0047 #include <vector>
0048
0049 #include "absl/base/attributes.h"
0050 #include "absl/base/config.h"
0051 #include "absl/base/internal/per_thread_tls.h"
0052 #include "absl/base/optimization.h"
0053 #include "absl/base/thread_annotations.h"
0054 #include "absl/profiling/internal/sample_recorder.h"
0055 #include "absl/synchronization/mutex.h"
0056 #include "absl/time/time.h"
0057 #include "absl/utility/utility.h"
0058
0059 namespace absl {
0060 ABSL_NAMESPACE_BEGIN
0061 namespace container_internal {
0062
0063
0064
0065
0066 struct HashtablezInfo : public profiling_internal::Sample<HashtablezInfo> {
0067
0068 HashtablezInfo();
0069 ~HashtablezInfo();
0070 HashtablezInfo(const HashtablezInfo&) = delete;
0071 HashtablezInfo& operator=(const HashtablezInfo&) = delete;
0072
0073
0074
0075 void PrepareForSampling(int64_t stride, size_t inline_element_size_value,
0076 size_t key_size, size_t value_size,
0077 uint16_t soo_capacity_value)
0078 ABSL_EXCLUSIVE_LOCKS_REQUIRED(init_mu);
0079
0080
0081
0082 std::atomic<size_t> capacity;
0083 std::atomic<size_t> size;
0084 std::atomic<size_t> num_erases;
0085 std::atomic<size_t> num_rehashes;
0086 std::atomic<size_t> max_probe_length;
0087 std::atomic<size_t> total_probe_length;
0088 std::atomic<size_t> hashes_bitwise_or;
0089 std::atomic<size_t> hashes_bitwise_and;
0090 std::atomic<size_t> hashes_bitwise_xor;
0091 std::atomic<size_t> max_reserve;
0092
0093
0094
0095
0096
0097
0098 static constexpr int kMaxStackDepth = 64;
0099 absl::Time create_time;
0100 int32_t depth;
0101
0102
0103
0104
0105 uint16_t soo_capacity;
0106 void* stack[kMaxStackDepth];
0107 size_t inline_element_size;
0108 size_t key_size;
0109 size_t value_size;
0110 };
0111
0112 void RecordRehashSlow(HashtablezInfo* info, size_t total_probe_length);
0113
0114 void RecordReservationSlow(HashtablezInfo* info, size_t target_capacity);
0115
0116 void RecordClearedReservationSlow(HashtablezInfo* info);
0117
0118 void RecordStorageChangedSlow(HashtablezInfo* info, size_t size,
0119 size_t capacity);
0120
0121 void RecordInsertSlow(HashtablezInfo* info, size_t hash,
0122 size_t distance_from_desired);
0123
0124 void RecordEraseSlow(HashtablezInfo* info);
0125
0126 struct SamplingState {
0127 int64_t next_sample;
0128
0129
0130 int64_t sample_stride;
0131 };
0132
0133 HashtablezInfo* SampleSlow(SamplingState& next_sample,
0134 size_t inline_element_size, size_t key_size,
0135 size_t value_size, uint16_t soo_capacity);
0136 void UnsampleSlow(HashtablezInfo* info);
0137
0138 #if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
0139 #error ABSL_INTERNAL_HASHTABLEZ_SAMPLE cannot be directly set
0140 #endif
0141
0142 #if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
0143 class HashtablezInfoHandle {
0144 public:
0145 explicit HashtablezInfoHandle() : info_(nullptr) {}
0146 explicit HashtablezInfoHandle(HashtablezInfo* info) : info_(info) {}
0147
0148
0149
0150 void Unregister() {
0151 if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
0152 UnsampleSlow(info_);
0153 }
0154
0155 inline bool IsSampled() const { return ABSL_PREDICT_FALSE(info_ != nullptr); }
0156
0157 inline void RecordStorageChanged(size_t size, size_t capacity) {
0158 if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
0159 RecordStorageChangedSlow(info_, size, capacity);
0160 }
0161
0162 inline void RecordRehash(size_t total_probe_length) {
0163 if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
0164 RecordRehashSlow(info_, total_probe_length);
0165 }
0166
0167 inline void RecordReservation(size_t target_capacity) {
0168 if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
0169 RecordReservationSlow(info_, target_capacity);
0170 }
0171
0172 inline void RecordClearedReservation() {
0173 if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
0174 RecordClearedReservationSlow(info_);
0175 }
0176
0177 inline void RecordInsert(size_t hash, size_t distance_from_desired) {
0178 if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
0179 RecordInsertSlow(info_, hash, distance_from_desired);
0180 }
0181
0182 inline void RecordErase() {
0183 if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
0184 RecordEraseSlow(info_);
0185 }
0186
0187 friend inline void swap(HashtablezInfoHandle& lhs,
0188 HashtablezInfoHandle& rhs) {
0189 std::swap(lhs.info_, rhs.info_);
0190 }
0191
0192 private:
0193 friend class HashtablezInfoHandlePeer;
0194 HashtablezInfo* info_;
0195 };
0196 #else
0197
0198
0199 class HashtablezInfoHandle {
0200 public:
0201 explicit HashtablezInfoHandle() = default;
0202 explicit HashtablezInfoHandle(std::nullptr_t) {}
0203
0204 inline void Unregister() {}
0205 inline bool IsSampled() const { return false; }
0206 inline void RecordStorageChanged(size_t , size_t ) {}
0207 inline void RecordRehash(size_t ) {}
0208 inline void RecordReservation(size_t ) {}
0209 inline void RecordClearedReservation() {}
0210 inline void RecordInsert(size_t , size_t ) {}
0211 inline void RecordErase() {}
0212
0213 friend inline void swap(HashtablezInfoHandle& ,
0214 HashtablezInfoHandle& ) {}
0215 };
0216 #endif
0217
0218 #if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
0219 extern ABSL_PER_THREAD_TLS_KEYWORD SamplingState global_next_sample;
0220 #endif
0221
0222
0223 inline HashtablezInfoHandle Sample(
0224 ABSL_ATTRIBUTE_UNUSED size_t inline_element_size,
0225 ABSL_ATTRIBUTE_UNUSED size_t key_size,
0226 ABSL_ATTRIBUTE_UNUSED size_t value_size,
0227 ABSL_ATTRIBUTE_UNUSED uint16_t soo_capacity) {
0228 #if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
0229 if (ABSL_PREDICT_TRUE(--global_next_sample.next_sample > 0)) {
0230 return HashtablezInfoHandle(nullptr);
0231 }
0232 return HashtablezInfoHandle(SampleSlow(global_next_sample,
0233 inline_element_size, key_size,
0234 value_size, soo_capacity));
0235 #else
0236 return HashtablezInfoHandle(nullptr);
0237 #endif
0238 }
0239
0240 using HashtablezSampler =
0241 ::absl::profiling_internal::SampleRecorder<HashtablezInfo>;
0242
0243
0244 HashtablezSampler& GlobalHashtablezSampler();
0245
0246 using HashtablezConfigListener = void (*)();
0247 void SetHashtablezConfigListener(HashtablezConfigListener l);
0248
0249
0250 bool IsHashtablezEnabled();
0251 void SetHashtablezEnabled(bool enabled);
0252 void SetHashtablezEnabledInternal(bool enabled);
0253
0254
0255 int32_t GetHashtablezSampleParameter();
0256 void SetHashtablezSampleParameter(int32_t rate);
0257 void SetHashtablezSampleParameterInternal(int32_t rate);
0258
0259
0260 size_t GetHashtablezMaxSamples();
0261 void SetHashtablezMaxSamples(size_t max);
0262 void SetHashtablezMaxSamplesInternal(size_t max);
0263
0264
0265
0266
0267
0268
0269 extern "C" bool ABSL_INTERNAL_C_SYMBOL(AbslContainerInternalSampleEverything)();
0270
0271 }
0272 ABSL_NAMESPACE_END
0273 }
0274
0275 #endif