From ec35402ac93f2f010087794d8216a235d5e62b79 Mon Sep 17 00:00:00 2001 From: Vitaly Goldshteyn Date: Thu, 12 Mar 2026 03:38:48 -0700 Subject: [PATCH] Fix sampling for the insert into a non-SOO table with capacity==1. RecordInsertMiss is where we increment size for hashtablez. This call was missing, so size was off by one. We can even end up with negative size if a later erase takes place on the same table. PiperOrigin-RevId: 882493632 Change-Id: Ifbb58fb2eaa0225d310c919bd0162dc2e0185d58 --- absl/container/internal/raw_hash_set.cc | 4 +++ absl/container/internal/raw_hash_set_test.cc | 33 ++++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/absl/container/internal/raw_hash_set.cc b/absl/container/internal/raw_hash_set.cc index 15d072a7..048d2ee6 100644 --- a/absl/container/internal/raw_hash_set.cc +++ b/absl/container/internal/raw_hash_set.cc @@ -1528,6 +1528,10 @@ std::pair PrepareInsertSmallNonSoo( if (common.capacity() == 1) { if (common.empty()) { IncrementSmallSizeNonSoo(common, policy); + if (common.has_infoz()) { + common.infoz().RecordInsertMiss(get_hash(common.seed().seed()), + /*distance_from_desired=*/0); + } return {SooControl(), common.slot_array()}; } else { return Grow1To3AndPrepareInsert(common, policy, get_hash); diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc index 9c33e3c7..952399ab 100644 --- a/absl/container/internal/raw_hash_set_test.cc +++ b/absl/container/internal/raw_hash_set_test.cc @@ -2878,8 +2878,9 @@ TYPED_TEST(RawHashSamplerTest, Sample) { } } -std::vector SampleSooMutation( - absl::FunctionRef mutate_table) { +template +std::vector SampleTableMutation( + absl::FunctionRef mutate_table) { // Enable the feature even if the prod default is off. SetSamplingRateTo1Percent(); @@ -2892,7 +2893,7 @@ std::vector SampleSooMutation( ++start_size; }); - std::vector tables; + std::vector tables; for (int i = 0; i < 1000000; ++i) { tables.emplace_back(); mutate_table(tables.back()); @@ -2911,6 +2912,16 @@ std::vector SampleSooMutation( return infos; } +std::vector SampleSooMutation( + absl::FunctionRef mutate_table) { + return SampleTableMutation(mutate_table); +} + +std::vector SampleNonSooMutation( + absl::FunctionRef mutate_table) { + return SampleTableMutation(mutate_table); +} + TEST(RawHashSamplerTest, SooTableInsertToEmpty) { if (SooInt32Table().capacity() != SooCapacity()) { CHECK_LT(sizeof(void*), 8) << "missing SOO coverage"; @@ -2956,6 +2967,22 @@ TEST(RawHashSamplerTest, SooTableRepeatedInsertEraseDoesNotOversample) { // instance. } +TEST(RawHashSamplerTest, NonSooTableRepeatedInsertEraseCountSizeRight) { + ASSERT_EQ(NonSooIntTable().capacity(), 0); + std::vector infos = + SampleNonSooMutation([](NonSooIntTable& t) { + for (int i = 0; i < 10; ++i) { + t.insert(1); + t.erase(1); + } + }); + for (const HashtablezInfo* info : infos) { + EXPECT_EQ(info->soo_capacity, 0); + ASSERT_EQ(info->capacity, 1); + ASSERT_EQ(info->size, 0); + } +} + // Verifies that copy-constructing or copy-assigning an SOO table does not // incorrectly trigger new sampling evaluations. TEST(RawHashSamplerTest, SooTableCopyDoesNotOversample) {