aboutsummaryrefslogtreecommitdiff
path: root/absl/container/internal/hashtablez_sampler.h
diff options
context:
space:
mode:
authorEvan Brown <ezb@google.com>2024-03-19 12:07:34 -0700
committerCopybara-Service <copybara-worker@google.com>2024-03-19 12:08:27 -0700
commit1980d7b98a0cae64432ccf9c4afebda5e21b2c5e (patch)
tree89fa98715f94d4f0221080158e1c798dc5cf52c0 /absl/container/internal/hashtablez_sampler.h
parent43c36ffae6256b4c93c1b9d3c73efaf8c2c891ab (diff)
downloadabseil-1980d7b98a0cae64432ccf9c4afebda5e21b2c5e.tar.gz
abseil-1980d7b98a0cae64432ccf9c4afebda5e21b2c5e.tar.bz2
abseil-1980d7b98a0cae64432ccf9c4afebda5e21b2c5e.zip
Do hashtablez sampling on the first insertion into an empty SOO hashtable.
When sampling triggers, we skip SOO and allocate a backing array. We must do this because the HashtablezInfoHandle is part of the heap allocation (along with the control bytes and slots). By default, we sample 1 in ~1024 hashtables when sampling is enabled. This will impact performance because (a) we won't benefit from SOO so we would have worse data locality (more cache/TLB misses), and (b) the backing array capacity will be 3 instead of 1 so (b.1) we skip the rehash after the second insertion and (b.2) we potentially waste up to two slots worth of memory. We also add an soo_capacity field to HashtablezInfo to allow for distinguishing which sampled tables may otherwise have been SOO - this will allow us to know approximately what fraction of tables are in SOO mode. PiperOrigin-RevId: 617252334 Change-Id: Ib48b7a4870bd74ea3ba923ed8f350a3b75dbb7d3
Diffstat (limited to 'absl/container/internal/hashtablez_sampler.h')
-rw-r--r--absl/container/internal/hashtablez_sampler.h25
1 files changed, 18 insertions, 7 deletions
diff --git a/absl/container/internal/hashtablez_sampler.h b/absl/container/internal/hashtablez_sampler.h
index e41ee2d7..4e11968d 100644
--- a/absl/container/internal/hashtablez_sampler.h
+++ b/absl/container/internal/hashtablez_sampler.h
@@ -40,15 +40,20 @@
#define ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_
#include <atomic>
+#include <cstddef>
+#include <cstdint>
#include <functional>
#include <memory>
#include <vector>
+#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/per_thread_tls.h"
#include "absl/base/optimization.h"
+#include "absl/base/thread_annotations.h"
#include "absl/profiling/internal/sample_recorder.h"
#include "absl/synchronization/mutex.h"
+#include "absl/time/time.h"
#include "absl/utility/utility.h"
namespace absl {
@@ -67,7 +72,8 @@ struct HashtablezInfo : public profiling_internal::Sample<HashtablezInfo> {
// Puts the object into a clean state, fills in the logically `const` members,
// blocking for any readers that are currently sampling the object.
- void PrepareForSampling(int64_t stride, size_t inline_element_size_value)
+ void PrepareForSampling(int64_t stride, size_t inline_element_size_value,
+ uint16_t soo_capacity_value)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(init_mu);
// These fields are mutated by the various Record* APIs and need to be
@@ -91,8 +97,13 @@ struct HashtablezInfo : public profiling_internal::Sample<HashtablezInfo> {
static constexpr int kMaxStackDepth = 64;
absl::Time create_time;
int32_t depth;
+ // The SOO capacity for this table in elements (not bytes). Note that sampled
+ // tables are never SOO because we need to store the infoz handle on the heap.
+ // Tables that would be SOO if not sampled should have: soo_capacity > 0 &&
+ // size <= soo_capacity && max_reserve <= soo_capacity.
+ uint16_t soo_capacity;
void* stack[kMaxStackDepth];
- size_t inline_element_size; // How big is the slot?
+ size_t inline_element_size; // How big is the slot in bytes?
};
void RecordRehashSlow(HashtablezInfo* info, size_t total_probe_length);
@@ -117,7 +128,7 @@ struct SamplingState {
};
HashtablezInfo* SampleSlow(SamplingState& next_sample,
- size_t inline_element_size);
+ size_t inline_element_size, uint16_t soo_capacity);
void UnsampleSlow(HashtablezInfo* info);
#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
@@ -204,16 +215,16 @@ class HashtablezInfoHandle {
extern ABSL_PER_THREAD_TLS_KEYWORD SamplingState global_next_sample;
#endif // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
-// Returns an RAII sampling handle that manages registration and unregistation
-// with the global sampler.
+// Returns a sampling handle.
inline HashtablezInfoHandle Sample(
- size_t inline_element_size ABSL_ATTRIBUTE_UNUSED) {
+ ABSL_ATTRIBUTE_UNUSED size_t inline_element_size,
+ ABSL_ATTRIBUTE_UNUSED uint16_t soo_capacity) {
#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));
+ SampleSlow(global_next_sample, inline_element_size, soo_capacity));
#else
return HashtablezInfoHandle(nullptr);
#endif // !ABSL_PER_THREAD_TLS