| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #ifndef ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_ |
| #define ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_ |
|
|
| #include <atomic> |
| #include <functional> |
| #include <memory> |
| #include <vector> |
|
|
| #include "absl/base/config.h" |
| #include "absl/base/internal/per_thread_tls.h" |
| #include "absl/base/optimization.h" |
| #include "absl/profiling/internal/sample_recorder.h" |
| #include "absl/synchronization/mutex.h" |
| #include "absl/utility/utility.h" |
|
|
| namespace absl { |
| ABSL_NAMESPACE_BEGIN |
| namespace container_internal { |
|
|
| |
| |
| |
| struct HashtablezInfo : public profiling_internal::Sample<HashtablezInfo> { |
| |
| HashtablezInfo(); |
| ~HashtablezInfo(); |
| HashtablezInfo(const HashtablezInfo&) = delete; |
| HashtablezInfo& operator=(const HashtablezInfo&) = delete; |
|
|
| |
| |
| void PrepareForSampling(int64_t stride, size_t inline_element_size_value) |
| ABSL_EXCLUSIVE_LOCKS_REQUIRED(init_mu); |
|
|
| |
| |
| std::atomic<size_t> capacity; |
| std::atomic<size_t> size; |
| std::atomic<size_t> num_erases; |
| std::atomic<size_t> num_rehashes; |
| std::atomic<size_t> max_probe_length; |
| std::atomic<size_t> total_probe_length; |
| std::atomic<size_t> hashes_bitwise_or; |
| std::atomic<size_t> hashes_bitwise_and; |
| std::atomic<size_t> hashes_bitwise_xor; |
| std::atomic<size_t> max_reserve; |
|
|
| |
| |
| |
| |
| |
| static constexpr int kMaxStackDepth = 64; |
| absl::Time create_time; |
| int32_t depth; |
| void* stack[kMaxStackDepth]; |
| size_t inline_element_size; |
| }; |
|
|
| void RecordRehashSlow(HashtablezInfo* info, size_t total_probe_length); |
|
|
| void RecordReservationSlow(HashtablezInfo* info, size_t target_capacity); |
|
|
| void RecordClearedReservationSlow(HashtablezInfo* info); |
|
|
| void RecordStorageChangedSlow(HashtablezInfo* info, size_t size, |
| size_t capacity); |
|
|
| void RecordInsertSlow(HashtablezInfo* info, size_t hash, |
| size_t distance_from_desired); |
|
|
| void RecordEraseSlow(HashtablezInfo* info); |
|
|
| struct SamplingState { |
| int64_t next_sample; |
| |
| |
| int64_t sample_stride; |
| }; |
|
|
| HashtablezInfo* SampleSlow(SamplingState& next_sample, |
| size_t inline_element_size); |
| void UnsampleSlow(HashtablezInfo* info); |
|
|
| #if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) |
| #error ABSL_INTERNAL_HASHTABLEZ_SAMPLE cannot be directly set |
| #endif |
|
|
| #if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) |
| class HashtablezInfoHandle { |
| public: |
| explicit HashtablezInfoHandle() : info_(nullptr) {} |
| explicit HashtablezInfoHandle(HashtablezInfo* info) : info_(info) {} |
|
|
| |
| |
| void Unregister() { |
| if (ABSL_PREDICT_TRUE(info_ == nullptr)) return; |
| UnsampleSlow(info_); |
| } |
|
|
| inline bool IsSampled() const { return ABSL_PREDICT_FALSE(info_ != nullptr); } |
|
|
| inline void RecordStorageChanged(size_t size, size_t capacity) { |
| if (ABSL_PREDICT_TRUE(info_ == nullptr)) return; |
| RecordStorageChangedSlow(info_, size, capacity); |
| } |
|
|
| inline void RecordRehash(size_t total_probe_length) { |
| if (ABSL_PREDICT_TRUE(info_ == nullptr)) return; |
| RecordRehashSlow(info_, total_probe_length); |
| } |
|
|
| inline void RecordReservation(size_t target_capacity) { |
| if (ABSL_PREDICT_TRUE(info_ == nullptr)) return; |
| RecordReservationSlow(info_, target_capacity); |
| } |
|
|
| inline void RecordClearedReservation() { |
| if (ABSL_PREDICT_TRUE(info_ == nullptr)) return; |
| RecordClearedReservationSlow(info_); |
| } |
|
|
| inline void RecordInsert(size_t hash, size_t distance_from_desired) { |
| if (ABSL_PREDICT_TRUE(info_ == nullptr)) return; |
| RecordInsertSlow(info_, hash, distance_from_desired); |
| } |
|
|
| inline void RecordErase() { |
| if (ABSL_PREDICT_TRUE(info_ == nullptr)) return; |
| RecordEraseSlow(info_); |
| } |
|
|
| friend inline void swap(HashtablezInfoHandle& lhs, |
| HashtablezInfoHandle& rhs) { |
| std::swap(lhs.info_, rhs.info_); |
| } |
|
|
| private: |
| friend class HashtablezInfoHandlePeer; |
| HashtablezInfo* info_; |
| }; |
| #else |
| |
| |
| class HashtablezInfoHandle { |
| public: |
| explicit HashtablezInfoHandle() = default; |
| explicit HashtablezInfoHandle(std::nullptr_t) {} |
|
|
| inline void Unregister() {} |
| inline bool IsSampled() const { return false; } |
| inline void RecordStorageChanged(size_t , size_t ) {} |
| inline void RecordRehash(size_t ) {} |
| inline void RecordReservation(size_t ) {} |
| inline void RecordClearedReservation() {} |
| inline void RecordInsert(size_t , size_t ) {} |
| inline void RecordErase() {} |
|
|
| friend inline void swap(HashtablezInfoHandle& , |
| HashtablezInfoHandle& ) {} |
| }; |
| #endif |
|
|
| #if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) |
| extern ABSL_PER_THREAD_TLS_KEYWORD SamplingState global_next_sample; |
| #endif |
|
|
| |
| |
| inline HashtablezInfoHandle Sample( |
| size_t inline_element_size ABSL_ATTRIBUTE_UNUSED) { |
| #if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) |
| if (ABSL_PREDICT_TRUE(--global_next_sample.next_sample > 0)) { |
| return HashtablezInfoHandle(nullptr); |
| } |
| return HashtablezInfoHandle( |
| SampleSlow(global_next_sample, inline_element_size)); |
| #else |
| return HashtablezInfoHandle(nullptr); |
| #endif |
| } |
|
|
| using HashtablezSampler = |
| ::absl::profiling_internal::SampleRecorder<HashtablezInfo>; |
|
|
| |
| HashtablezSampler& GlobalHashtablezSampler(); |
|
|
| using HashtablezConfigListener = void (*)(); |
| void SetHashtablezConfigListener(HashtablezConfigListener l); |
|
|
| |
| bool IsHashtablezEnabled(); |
| void SetHashtablezEnabled(bool enabled); |
| void SetHashtablezEnabledInternal(bool enabled); |
|
|
| |
| int32_t GetHashtablezSampleParameter(); |
| void SetHashtablezSampleParameter(int32_t rate); |
| void SetHashtablezSampleParameterInternal(int32_t rate); |
|
|
| |
| size_t GetHashtablezMaxSamples(); |
| void SetHashtablezMaxSamples(size_t max); |
| void SetHashtablezMaxSamplesInternal(size_t max); |
|
|
| |
| |
| |
| |
| |
| extern "C" bool ABSL_INTERNAL_C_SYMBOL(AbslContainerInternalSampleEverything)(); |
|
|
| } |
| ABSL_NAMESPACE_END |
| } |
|
|
| #endif |
|
|