Commit 48abb9fe by Chris Kennelly Committed by Copybara-Service

Record sizeof(key_type), sizeof(value_type) in hashtable profiles.

This can identify situations where flat_hash_* is suboptimal for large
elements.

PiperOrigin-RevId: 618937993
Change-Id: I2bde069bc3526b14ad1718ba6f50467002aeed16
parent 06e11906
...@@ -79,6 +79,8 @@ HashtablezInfo::~HashtablezInfo() = default; ...@@ -79,6 +79,8 @@ HashtablezInfo::~HashtablezInfo() = default;
void HashtablezInfo::PrepareForSampling(int64_t stride, void HashtablezInfo::PrepareForSampling(int64_t stride,
size_t inline_element_size_value, size_t inline_element_size_value,
size_t key_size_value,
size_t value_size_value,
uint16_t soo_capacity_value) { uint16_t soo_capacity_value) {
capacity.store(0, std::memory_order_relaxed); capacity.store(0, std::memory_order_relaxed);
size.store(0, std::memory_order_relaxed); size.store(0, std::memory_order_relaxed);
...@@ -99,6 +101,8 @@ void HashtablezInfo::PrepareForSampling(int64_t stride, ...@@ -99,6 +101,8 @@ void HashtablezInfo::PrepareForSampling(int64_t stride,
depth = absl::GetStackTrace(stack, HashtablezInfo::kMaxStackDepth, depth = absl::GetStackTrace(stack, HashtablezInfo::kMaxStackDepth,
/* skip_count= */ 0); /* skip_count= */ 0);
inline_element_size = inline_element_size_value; inline_element_size = inline_element_size_value;
key_size = key_size_value;
value_size = value_size_value;
soo_capacity = soo_capacity_value; soo_capacity = soo_capacity_value;
} }
...@@ -123,12 +127,13 @@ static bool ShouldForceSampling() { ...@@ -123,12 +127,13 @@ static bool ShouldForceSampling() {
} }
HashtablezInfo* SampleSlow(SamplingState& next_sample, HashtablezInfo* SampleSlow(SamplingState& next_sample,
size_t inline_element_size, uint16_t soo_capacity) { size_t inline_element_size, size_t key_size,
size_t value_size, uint16_t soo_capacity) {
if (ABSL_PREDICT_FALSE(ShouldForceSampling())) { if (ABSL_PREDICT_FALSE(ShouldForceSampling())) {
next_sample.next_sample = 1; next_sample.next_sample = 1;
const int64_t old_stride = exchange(next_sample.sample_stride, 1); const int64_t old_stride = exchange(next_sample.sample_stride, 1);
HashtablezInfo* result = GlobalHashtablezSampler().Register( HashtablezInfo* result = GlobalHashtablezSampler().Register(
old_stride, inline_element_size, soo_capacity); old_stride, inline_element_size, key_size, value_size, soo_capacity);
return result; return result;
} }
...@@ -158,11 +163,12 @@ HashtablezInfo* SampleSlow(SamplingState& next_sample, ...@@ -158,11 +163,12 @@ HashtablezInfo* SampleSlow(SamplingState& next_sample,
// that case. // that case.
if (first) { if (first) {
if (ABSL_PREDICT_TRUE(--next_sample.next_sample > 0)) return nullptr; if (ABSL_PREDICT_TRUE(--next_sample.next_sample > 0)) return nullptr;
return SampleSlow(next_sample, inline_element_size, soo_capacity); return SampleSlow(next_sample, inline_element_size, key_size, value_size,
soo_capacity);
} }
return GlobalHashtablezSampler().Register(old_stride, inline_element_size, return GlobalHashtablezSampler().Register(old_stride, inline_element_size,
soo_capacity); key_size, value_size, soo_capacity);
#endif #endif
} }
......
...@@ -73,6 +73,7 @@ struct HashtablezInfo : public profiling_internal::Sample<HashtablezInfo> { ...@@ -73,6 +73,7 @@ struct HashtablezInfo : public profiling_internal::Sample<HashtablezInfo> {
// Puts the object into a clean state, fills in the logically `const` members, // Puts the object into a clean state, fills in the logically `const` members,
// blocking for any readers that are currently sampling the object. // 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,
size_t key_size, size_t value_size,
uint16_t soo_capacity_value) uint16_t soo_capacity_value)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(init_mu); ABSL_EXCLUSIVE_LOCKS_REQUIRED(init_mu);
...@@ -104,6 +105,8 @@ struct HashtablezInfo : public profiling_internal::Sample<HashtablezInfo> { ...@@ -104,6 +105,8 @@ struct HashtablezInfo : public profiling_internal::Sample<HashtablezInfo> {
uint16_t soo_capacity; uint16_t soo_capacity;
void* stack[kMaxStackDepth]; void* stack[kMaxStackDepth];
size_t inline_element_size; // How big is the slot in bytes? size_t inline_element_size; // How big is the slot in bytes?
size_t key_size; // sizeof(key_type)
size_t value_size; // sizeof(value_type)
}; };
void RecordRehashSlow(HashtablezInfo* info, size_t total_probe_length); void RecordRehashSlow(HashtablezInfo* info, size_t total_probe_length);
...@@ -128,7 +131,8 @@ struct SamplingState { ...@@ -128,7 +131,8 @@ struct SamplingState {
}; };
HashtablezInfo* SampleSlow(SamplingState& next_sample, HashtablezInfo* SampleSlow(SamplingState& next_sample,
size_t inline_element_size, uint16_t soo_capacity); size_t inline_element_size, size_t key_size,
size_t value_size, uint16_t soo_capacity);
void UnsampleSlow(HashtablezInfo* info); void UnsampleSlow(HashtablezInfo* info);
#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) #if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
...@@ -218,13 +222,16 @@ extern ABSL_PER_THREAD_TLS_KEYWORD SamplingState global_next_sample; ...@@ -218,13 +222,16 @@ extern ABSL_PER_THREAD_TLS_KEYWORD SamplingState global_next_sample;
// Returns a sampling handle. // Returns a sampling handle.
inline HashtablezInfoHandle Sample( inline HashtablezInfoHandle Sample(
ABSL_ATTRIBUTE_UNUSED size_t inline_element_size, ABSL_ATTRIBUTE_UNUSED size_t inline_element_size,
ABSL_ATTRIBUTE_UNUSED size_t key_size,
ABSL_ATTRIBUTE_UNUSED size_t value_size,
ABSL_ATTRIBUTE_UNUSED uint16_t soo_capacity) { ABSL_ATTRIBUTE_UNUSED uint16_t soo_capacity) {
#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) #if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
if (ABSL_PREDICT_TRUE(--global_next_sample.next_sample > 0)) { if (ABSL_PREDICT_TRUE(--global_next_sample.next_sample > 0)) {
return HashtablezInfoHandle(nullptr); return HashtablezInfoHandle(nullptr);
} }
return HashtablezInfoHandle( return HashtablezInfoHandle(SampleSlow(global_next_sample,
SampleSlow(global_next_sample, inline_element_size, soo_capacity)); inline_element_size, key_size,
value_size, soo_capacity));
#else #else
return HashtablezInfoHandle(nullptr); return HashtablezInfoHandle(nullptr);
#endif // !ABSL_PER_THREAD_TLS #endif // !ABSL_PER_THREAD_TLS
......
...@@ -71,7 +71,11 @@ std::vector<size_t> GetSizes(HashtablezSampler* s) { ...@@ -71,7 +71,11 @@ std::vector<size_t> GetSizes(HashtablezSampler* s) {
HashtablezInfo* Register(HashtablezSampler* s, size_t size) { HashtablezInfo* Register(HashtablezSampler* s, size_t size) {
const int64_t test_stride = 123; const int64_t test_stride = 123;
const size_t test_element_size = 17; const size_t test_element_size = 17;
auto* info = s->Register(test_stride, test_element_size, /*soo_capacity=*/0); const size_t test_key_size = 3;
const size_t test_value_size = 5;
auto* info =
s->Register(test_stride, test_element_size, /*key_size=*/test_key_size,
/*value_size=*/test_value_size, /*soo_capacity=*/0);
assert(info != nullptr); assert(info != nullptr);
info->size.store(size); info->size.store(size);
return info; return info;
...@@ -81,9 +85,14 @@ TEST(HashtablezInfoTest, PrepareForSampling) { ...@@ -81,9 +85,14 @@ TEST(HashtablezInfoTest, PrepareForSampling) {
absl::Time test_start = absl::Now(); absl::Time test_start = absl::Now();
const int64_t test_stride = 123; const int64_t test_stride = 123;
const size_t test_element_size = 17; const size_t test_element_size = 17;
const size_t test_key_size = 15;
const size_t test_value_size = 13;
HashtablezInfo info; HashtablezInfo info;
absl::MutexLock l(&info.init_mu); absl::MutexLock l(&info.init_mu);
info.PrepareForSampling(test_stride, test_element_size, info.PrepareForSampling(test_stride, test_element_size,
/*key_size=*/test_key_size,
/*value_size=*/test_value_size,
/*soo_capacity_value=*/1); /*soo_capacity_value=*/1);
EXPECT_EQ(info.capacity.load(), 0); EXPECT_EQ(info.capacity.load(), 0);
...@@ -99,6 +108,8 @@ TEST(HashtablezInfoTest, PrepareForSampling) { ...@@ -99,6 +108,8 @@ TEST(HashtablezInfoTest, PrepareForSampling) {
EXPECT_GE(info.create_time, test_start); EXPECT_GE(info.create_time, test_start);
EXPECT_EQ(info.weight, test_stride); EXPECT_EQ(info.weight, test_stride);
EXPECT_EQ(info.inline_element_size, test_element_size); EXPECT_EQ(info.inline_element_size, test_element_size);
EXPECT_EQ(info.key_size, test_key_size);
EXPECT_EQ(info.value_size, test_value_size);
EXPECT_EQ(info.soo_capacity, 1); EXPECT_EQ(info.soo_capacity, 1);
info.capacity.store(1, std::memory_order_relaxed); info.capacity.store(1, std::memory_order_relaxed);
...@@ -113,6 +124,8 @@ TEST(HashtablezInfoTest, PrepareForSampling) { ...@@ -113,6 +124,8 @@ TEST(HashtablezInfoTest, PrepareForSampling) {
info.create_time = test_start - absl::Hours(20); info.create_time = test_start - absl::Hours(20);
info.PrepareForSampling(test_stride * 2, test_element_size, info.PrepareForSampling(test_stride * 2, test_element_size,
/*key_size=*/test_key_size,
/*value_size=*/test_value_size,
/*soo_capacity_value=*/0); /*soo_capacity_value=*/0);
EXPECT_EQ(info.capacity.load(), 0); EXPECT_EQ(info.capacity.load(), 0);
EXPECT_EQ(info.size.load(), 0); EXPECT_EQ(info.size.load(), 0);
...@@ -126,6 +139,8 @@ TEST(HashtablezInfoTest, PrepareForSampling) { ...@@ -126,6 +139,8 @@ TEST(HashtablezInfoTest, PrepareForSampling) {
EXPECT_EQ(info.max_reserve.load(), 0); EXPECT_EQ(info.max_reserve.load(), 0);
EXPECT_EQ(info.weight, 2 * test_stride); EXPECT_EQ(info.weight, 2 * test_stride);
EXPECT_EQ(info.inline_element_size, test_element_size); EXPECT_EQ(info.inline_element_size, test_element_size);
EXPECT_EQ(info.key_size, test_key_size);
EXPECT_EQ(info.value_size, test_value_size);
EXPECT_GE(info.create_time, test_start); EXPECT_GE(info.create_time, test_start);
EXPECT_EQ(info.soo_capacity, 0); EXPECT_EQ(info.soo_capacity, 0);
} }
...@@ -135,7 +150,12 @@ TEST(HashtablezInfoTest, RecordStorageChanged) { ...@@ -135,7 +150,12 @@ TEST(HashtablezInfoTest, RecordStorageChanged) {
absl::MutexLock l(&info.init_mu); absl::MutexLock l(&info.init_mu);
const int64_t test_stride = 21; const int64_t test_stride = 21;
const size_t test_element_size = 19; const size_t test_element_size = 19;
const size_t test_key_size = 17;
const size_t test_value_size = 15;
info.PrepareForSampling(test_stride, test_element_size, info.PrepareForSampling(test_stride, test_element_size,
/*key_size=*/test_key_size,
/*value_size=*/test_value_size,
/*soo_capacity_value=*/0); /*soo_capacity_value=*/0);
RecordStorageChangedSlow(&info, 17, 47); RecordStorageChangedSlow(&info, 17, 47);
EXPECT_EQ(info.size.load(), 17); EXPECT_EQ(info.size.load(), 17);
...@@ -150,7 +170,12 @@ TEST(HashtablezInfoTest, RecordInsert) { ...@@ -150,7 +170,12 @@ TEST(HashtablezInfoTest, RecordInsert) {
absl::MutexLock l(&info.init_mu); absl::MutexLock l(&info.init_mu);
const int64_t test_stride = 25; const int64_t test_stride = 25;
const size_t test_element_size = 23; const size_t test_element_size = 23;
const size_t test_key_size = 21;
const size_t test_value_size = 19;
info.PrepareForSampling(test_stride, test_element_size, info.PrepareForSampling(test_stride, test_element_size,
/*key_size=*/test_key_size,
/*value_size=*/test_value_size,
/*soo_capacity_value=*/0); /*soo_capacity_value=*/0);
EXPECT_EQ(info.max_probe_length.load(), 0); EXPECT_EQ(info.max_probe_length.load(), 0);
RecordInsertSlow(&info, 0x0000FF00, 6 * kProbeLength); RecordInsertSlow(&info, 0x0000FF00, 6 * kProbeLength);
...@@ -173,9 +198,14 @@ TEST(HashtablezInfoTest, RecordInsert) { ...@@ -173,9 +198,14 @@ TEST(HashtablezInfoTest, RecordInsert) {
TEST(HashtablezInfoTest, RecordErase) { TEST(HashtablezInfoTest, RecordErase) {
const int64_t test_stride = 31; const int64_t test_stride = 31;
const size_t test_element_size = 29; const size_t test_element_size = 29;
const size_t test_key_size = 27;
const size_t test_value_size = 25;
HashtablezInfo info; HashtablezInfo info;
absl::MutexLock l(&info.init_mu); absl::MutexLock l(&info.init_mu);
info.PrepareForSampling(test_stride, test_element_size, info.PrepareForSampling(test_stride, test_element_size,
/*key_size=*/test_key_size,
/*value_size=*/test_value_size,
/*soo_capacity_value=*/1); /*soo_capacity_value=*/1);
EXPECT_EQ(info.num_erases.load(), 0); EXPECT_EQ(info.num_erases.load(), 0);
EXPECT_EQ(info.size.load(), 0); EXPECT_EQ(info.size.load(), 0);
...@@ -185,15 +215,22 @@ TEST(HashtablezInfoTest, RecordErase) { ...@@ -185,15 +215,22 @@ TEST(HashtablezInfoTest, RecordErase) {
EXPECT_EQ(info.size.load(), 0); EXPECT_EQ(info.size.load(), 0);
EXPECT_EQ(info.num_erases.load(), 1); EXPECT_EQ(info.num_erases.load(), 1);
EXPECT_EQ(info.inline_element_size, test_element_size); EXPECT_EQ(info.inline_element_size, test_element_size);
EXPECT_EQ(info.key_size, test_key_size);
EXPECT_EQ(info.value_size, test_value_size);
EXPECT_EQ(info.soo_capacity, 1); EXPECT_EQ(info.soo_capacity, 1);
} }
TEST(HashtablezInfoTest, RecordRehash) { TEST(HashtablezInfoTest, RecordRehash) {
const int64_t test_stride = 33; const int64_t test_stride = 33;
const size_t test_element_size = 31; const size_t test_element_size = 31;
const size_t test_key_size = 29;
const size_t test_value_size = 27;
HashtablezInfo info; HashtablezInfo info;
absl::MutexLock l(&info.init_mu); absl::MutexLock l(&info.init_mu);
info.PrepareForSampling(test_stride, test_element_size, info.PrepareForSampling(test_stride, test_element_size,
/*key_size=*/test_key_size,
/*value_size=*/test_value_size,
/*soo_capacity_value=*/0); /*soo_capacity_value=*/0);
RecordInsertSlow(&info, 0x1, 0); RecordInsertSlow(&info, 0x1, 0);
RecordInsertSlow(&info, 0x2, kProbeLength); RecordInsertSlow(&info, 0x2, kProbeLength);
...@@ -214,6 +251,8 @@ TEST(HashtablezInfoTest, RecordRehash) { ...@@ -214,6 +251,8 @@ TEST(HashtablezInfoTest, RecordRehash) {
EXPECT_EQ(info.num_erases.load(), 0); EXPECT_EQ(info.num_erases.load(), 0);
EXPECT_EQ(info.num_rehashes.load(), 1); EXPECT_EQ(info.num_rehashes.load(), 1);
EXPECT_EQ(info.inline_element_size, test_element_size); EXPECT_EQ(info.inline_element_size, test_element_size);
EXPECT_EQ(info.key_size, test_key_size);
EXPECT_EQ(info.value_size, test_value_size);
EXPECT_EQ(info.soo_capacity, 0); EXPECT_EQ(info.soo_capacity, 0);
} }
...@@ -222,7 +261,13 @@ TEST(HashtablezInfoTest, RecordReservation) { ...@@ -222,7 +261,13 @@ TEST(HashtablezInfoTest, RecordReservation) {
absl::MutexLock l(&info.init_mu); absl::MutexLock l(&info.init_mu);
const int64_t test_stride = 35; const int64_t test_stride = 35;
const size_t test_element_size = 33; const size_t test_element_size = 33;
const size_t test_key_size = 31;
const size_t test_value_size = 29;
info.PrepareForSampling(test_stride, test_element_size, info.PrepareForSampling(test_stride, test_element_size,
/*key_size=*/test_key_size,
/*value_size=*/test_value_size,
/*soo_capacity_value=*/0); /*soo_capacity_value=*/0);
RecordReservationSlow(&info, 3); RecordReservationSlow(&info, 3);
EXPECT_EQ(info.max_reserve.load(), 3); EXPECT_EQ(info.max_reserve.load(), 3);
...@@ -239,13 +284,19 @@ TEST(HashtablezInfoTest, RecordReservation) { ...@@ -239,13 +284,19 @@ TEST(HashtablezInfoTest, RecordReservation) {
#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE) #if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
TEST(HashtablezSamplerTest, SmallSampleParameter) { TEST(HashtablezSamplerTest, SmallSampleParameter) {
const size_t test_element_size = 31; const size_t test_element_size = 31;
const size_t test_key_size = 33;
const size_t test_value_size = 35;
SetHashtablezEnabled(true); SetHashtablezEnabled(true);
SetHashtablezSampleParameter(100); SetHashtablezSampleParameter(100);
for (int i = 0; i < 1000; ++i) { for (int i = 0; i < 1000; ++i) {
SamplingState next_sample = {0, 0}; SamplingState next_sample = {0, 0};
HashtablezInfo* sample = SampleSlow(next_sample, test_element_size, HashtablezInfo* sample =
/*soo_capacity=*/0); SampleSlow(next_sample, test_element_size,
/*key_size=*/test_key_size, /*value_size=*/test_value_size,
/*soo_capacity=*/0);
EXPECT_GT(next_sample.next_sample, 0); EXPECT_GT(next_sample.next_sample, 0);
EXPECT_EQ(next_sample.next_sample, next_sample.sample_stride); EXPECT_EQ(next_sample.next_sample, next_sample.sample_stride);
EXPECT_NE(sample, nullptr); EXPECT_NE(sample, nullptr);
...@@ -255,13 +306,17 @@ TEST(HashtablezSamplerTest, SmallSampleParameter) { ...@@ -255,13 +306,17 @@ TEST(HashtablezSamplerTest, SmallSampleParameter) {
TEST(HashtablezSamplerTest, LargeSampleParameter) { TEST(HashtablezSamplerTest, LargeSampleParameter) {
const size_t test_element_size = 31; const size_t test_element_size = 31;
const size_t test_key_size = 33;
const size_t test_value_size = 35;
SetHashtablezEnabled(true); SetHashtablezEnabled(true);
SetHashtablezSampleParameter(std::numeric_limits<int32_t>::max()); SetHashtablezSampleParameter(std::numeric_limits<int32_t>::max());
for (int i = 0; i < 1000; ++i) { for (int i = 0; i < 1000; ++i) {
SamplingState next_sample = {0, 0}; SamplingState next_sample = {0, 0};
HashtablezInfo* sample = SampleSlow(next_sample, test_element_size, HashtablezInfo* sample =
/*soo_capacity=*/0); SampleSlow(next_sample, test_element_size,
/*key_size=*/test_key_size, /*value_size=*/test_value_size,
/*soo_capacity=*/0);
EXPECT_GT(next_sample.next_sample, 0); EXPECT_GT(next_sample.next_sample, 0);
EXPECT_EQ(next_sample.next_sample, next_sample.sample_stride); EXPECT_EQ(next_sample.next_sample, next_sample.sample_stride);
EXPECT_NE(sample, nullptr); EXPECT_NE(sample, nullptr);
...@@ -271,14 +326,20 @@ TEST(HashtablezSamplerTest, LargeSampleParameter) { ...@@ -271,14 +326,20 @@ TEST(HashtablezSamplerTest, LargeSampleParameter) {
TEST(HashtablezSamplerTest, Sample) { TEST(HashtablezSamplerTest, Sample) {
const size_t test_element_size = 31; const size_t test_element_size = 31;
const size_t test_key_size = 33;
const size_t test_value_size = 35;
SetHashtablezEnabled(true); SetHashtablezEnabled(true);
SetHashtablezSampleParameter(100); SetHashtablezSampleParameter(100);
int64_t num_sampled = 0; int64_t num_sampled = 0;
int64_t total = 0; int64_t total = 0;
double sample_rate = 0.0; double sample_rate = 0.0;
for (int i = 0; i < 1000000; ++i) { for (int i = 0; i < 1000000; ++i) {
HashtablezInfoHandle h = Sample(test_element_size, HashtablezInfoHandle h =
/*soo_capacity=*/0); Sample(test_element_size,
/*key_size=*/test_key_size, /*value_size=*/test_value_size,
/*soo_capacity=*/0);
++total; ++total;
if (h.IsSampled()) { if (h.IsSampled()) {
++num_sampled; ++num_sampled;
...@@ -293,7 +354,11 @@ TEST(HashtablezSamplerTest, Handle) { ...@@ -293,7 +354,11 @@ TEST(HashtablezSamplerTest, Handle) {
auto& sampler = GlobalHashtablezSampler(); auto& sampler = GlobalHashtablezSampler();
const int64_t test_stride = 41; const int64_t test_stride = 41;
const size_t test_element_size = 39; const size_t test_element_size = 39;
const size_t test_key_size = 37;
const size_t test_value_size = 35;
HashtablezInfoHandle h(sampler.Register(test_stride, test_element_size, HashtablezInfoHandle h(sampler.Register(test_stride, test_element_size,
/*key_size=*/test_key_size,
/*value_size=*/test_value_size,
/*soo_capacity=*/0)); /*soo_capacity=*/0));
auto* info = HashtablezInfoHandlePeer::GetInfo(&h); auto* info = HashtablezInfoHandlePeer::GetInfo(&h);
info->hashes_bitwise_and.store(0x12345678, std::memory_order_relaxed); info->hashes_bitwise_and.store(0x12345678, std::memory_order_relaxed);
...@@ -370,7 +435,10 @@ TEST(HashtablezSamplerTest, MultiThreaded) { ...@@ -370,7 +435,10 @@ TEST(HashtablezSamplerTest, MultiThreaded) {
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
const int64_t sampling_stride = 11 + i % 3; const int64_t sampling_stride = 11 + i % 3;
const size_t elt_size = 10 + i % 2; const size_t elt_size = 10 + i % 2;
pool.Schedule([&sampler, &stop, sampling_stride, elt_size]() { const size_t key_size = 12 + i % 4;
const size_t value_size = 13 + i % 5;
pool.Schedule([&sampler, &stop, sampling_stride, elt_size, key_size,
value_size]() {
std::random_device rd; std::random_device rd;
std::mt19937 gen(rd()); std::mt19937 gen(rd());
...@@ -378,11 +446,16 @@ TEST(HashtablezSamplerTest, MultiThreaded) { ...@@ -378,11 +446,16 @@ TEST(HashtablezSamplerTest, MultiThreaded) {
while (!stop.HasBeenNotified()) { while (!stop.HasBeenNotified()) {
if (infoz.empty()) { if (infoz.empty()) {
infoz.push_back(sampler.Register(sampling_stride, elt_size, infoz.push_back(sampler.Register(sampling_stride, elt_size,
/*key_size=*/key_size,
/*value_size=*/value_size,
/*soo_capacity=*/0)); /*soo_capacity=*/0));
} }
switch (std::uniform_int_distribution<>(0, 2)(gen)) { switch (std::uniform_int_distribution<>(0, 2)(gen)) {
case 0: { case 0: {
infoz.push_back(sampler.Register(sampling_stride, elt_size, infoz.push_back(sampler.Register(sampling_stride, elt_size,
/*key_size=*/key_size,
/*value_size=*/value_size,
/*soo_capacity=*/0)); /*soo_capacity=*/0));
break; break;
} }
......
...@@ -1786,7 +1786,8 @@ constexpr bool ShouldSampleHashtablezInfo() { ...@@ -1786,7 +1786,8 @@ constexpr bool ShouldSampleHashtablezInfo() {
} }
template <bool kSooEnabled> template <bool kSooEnabled>
HashtablezInfoHandle SampleHashtablezInfo(size_t sizeof_slot, HashtablezInfoHandle SampleHashtablezInfo(size_t sizeof_slot, size_t sizeof_key,
size_t sizeof_value,
size_t old_capacity, bool was_soo, size_t old_capacity, bool was_soo,
HashtablezInfoHandle forced_infoz, HashtablezInfoHandle forced_infoz,
CommonFields& c) { CommonFields& c) {
...@@ -1794,12 +1795,12 @@ HashtablezInfoHandle SampleHashtablezInfo(size_t sizeof_slot, ...@@ -1794,12 +1795,12 @@ HashtablezInfoHandle SampleHashtablezInfo(size_t sizeof_slot,
// In SOO, we sample on the first insertion so if this is an empty SOO case // In SOO, we sample on the first insertion so if this is an empty SOO case
// (e.g. when reserve is called), then we still need to sample. // (e.g. when reserve is called), then we still need to sample.
if (kSooEnabled && was_soo && c.size() == 0) { if (kSooEnabled && was_soo && c.size() == 0) {
return Sample(sizeof_slot, SooCapacity()); return Sample(sizeof_slot, sizeof_key, sizeof_value, SooCapacity());
} }
// For non-SOO cases, we sample whenever the capacity is increasing from zero // For non-SOO cases, we sample whenever the capacity is increasing from zero
// to non-zero. // to non-zero.
if (!kSooEnabled && old_capacity == 0) { if (!kSooEnabled && old_capacity == 0) {
return Sample(sizeof_slot, 0); return Sample(sizeof_slot, sizeof_key, sizeof_value, 0);
} }
return c.infoz(); return c.infoz();
} }
...@@ -1902,12 +1903,15 @@ class HashSetResizeHelper { ...@@ -1902,12 +1903,15 @@ class HashSetResizeHelper {
template <typename Alloc, size_t SizeOfSlot, bool TransferUsesMemcpy, template <typename Alloc, size_t SizeOfSlot, bool TransferUsesMemcpy,
bool SooEnabled, size_t AlignOfSlot> bool SooEnabled, size_t AlignOfSlot>
ABSL_ATTRIBUTE_NOINLINE bool InitializeSlots(CommonFields& c, Alloc alloc, ABSL_ATTRIBUTE_NOINLINE bool InitializeSlots(CommonFields& c, Alloc alloc,
ctrl_t soo_slot_h2) { ctrl_t soo_slot_h2,
size_t key_size,
size_t value_size) {
assert(c.capacity()); assert(c.capacity());
HashtablezInfoHandle infoz = HashtablezInfoHandle infoz =
ShouldSampleHashtablezInfo<Alloc>() ShouldSampleHashtablezInfo<Alloc>()
? SampleHashtablezInfo<SooEnabled>(SizeOfSlot, old_capacity_, ? SampleHashtablezInfo<SooEnabled>(SizeOfSlot, key_size, value_size,
was_soo_, forced_infoz_, c) old_capacity_, was_soo_,
forced_infoz_, c)
: HashtablezInfoHandle{}; : HashtablezInfoHandle{};
const bool has_infoz = infoz.IsSampled(); const bool has_infoz = infoz.IsSampled();
...@@ -3362,7 +3366,8 @@ class raw_hash_set { ...@@ -3362,7 +3366,8 @@ class raw_hash_set {
inline HashtablezInfoHandle try_sample_soo() { inline HashtablezInfoHandle try_sample_soo() {
assert(is_soo()); assert(is_soo());
if (!ShouldSampleHashtablezInfo<CharAlloc>()) return HashtablezInfoHandle{}; if (!ShouldSampleHashtablezInfo<CharAlloc>()) return HashtablezInfoHandle{};
return Sample(sizeof(slot_type), SooCapacity()); return Sample(sizeof(slot_type), sizeof(key_type), sizeof(value_type),
SooCapacity());
} }
inline void destroy_slots() { inline void destroy_slots() {
...@@ -3458,7 +3463,8 @@ class raw_hash_set { ...@@ -3458,7 +3463,8 @@ class raw_hash_set {
resize_helper.InitializeSlots<CharAlloc, sizeof(slot_type), resize_helper.InitializeSlots<CharAlloc, sizeof(slot_type),
PolicyTraits::transfer_uses_memcpy(), PolicyTraits::transfer_uses_memcpy(),
SooEnabled(), alignof(slot_type)>( SooEnabled(), alignof(slot_type)>(
common(), CharAlloc(alloc_ref()), soo_slot_h2); common(), CharAlloc(alloc_ref()), soo_slot_h2, sizeof(key_type),
sizeof(value_type));
// In the SooEnabled() case, capacity is never 0 so we don't check. // In the SooEnabled() case, capacity is never 0 so we don't check.
if (!SooEnabled() && resize_helper.old_capacity() == 0) { if (!SooEnabled() && resize_helper.old_capacity() == 0) {
......
...@@ -2571,6 +2571,8 @@ TYPED_TEST_P(RawHashSamplerTest, Sample) { ...@@ -2571,6 +2571,8 @@ TYPED_TEST_P(RawHashSamplerTest, Sample) {
std::memory_order_relaxed)]++; std::memory_order_relaxed)]++;
reservations[info.max_reserve.load(std::memory_order_relaxed)]++; reservations[info.max_reserve.load(std::memory_order_relaxed)]++;
EXPECT_EQ(info.inline_element_size, sizeof(typename TypeParam::value_type)); EXPECT_EQ(info.inline_element_size, sizeof(typename TypeParam::value_type));
EXPECT_EQ(info.key_size, sizeof(typename TypeParam::key_type));
EXPECT_EQ(info.value_size, sizeof(typename TypeParam::value_type));
if (soo_enabled) { if (soo_enabled) {
EXPECT_EQ(info.soo_capacity, SooCapacity()); EXPECT_EQ(info.soo_capacity, SooCapacity());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment