mirror of
https://github.com/abseil/abseil-cpp.git
synced 2026-06-04 12:07:05 +08:00
Do not reserve space for GrowthInfo for single element tables in non-SOO case.
That would save 8 bytes of allocation size for such tables. PiperOrigin-RevId: 918340255 Change-Id: Ic5f00dfb87392089ac04242418e4f55cc599619e
This commit is contained in:
committed by
Copybara-Service
parent
8fb4507d10
commit
c508bab517
@@ -822,11 +822,15 @@ void ResizeNonSooImpl(CommonFields& common,
|
||||
common, policy, old_ctrl, old_slots, old_capacity);
|
||||
(*policy.dealloc)(alloc, old_capacity, old_ctrl, slot_size, slot_align,
|
||||
has_infoz);
|
||||
ResetGrowthLeft(GetGrowthInfoFromControl(new_ctrl), new_capacity,
|
||||
common.size());
|
||||
if (HasGrowthInfoForCapacity(new_capacity)) {
|
||||
ResetGrowthLeft(GetGrowthInfoFromControl(new_ctrl), new_capacity,
|
||||
common.size());
|
||||
}
|
||||
} else {
|
||||
GetGrowthInfoFromControl(new_ctrl).InitGrowthLeftNoDeleted(
|
||||
CapacityToGrowth(new_capacity));
|
||||
if (HasGrowthInfoForCapacity(new_capacity)) {
|
||||
GetGrowthInfoFromControl(new_ctrl).InitGrowthLeftNoDeleted(
|
||||
CapacityToGrowth(new_capacity));
|
||||
}
|
||||
}
|
||||
|
||||
if (ABSL_PREDICT_FALSE(has_infoz)) {
|
||||
@@ -1215,7 +1219,8 @@ class ProbedItemEncoder {
|
||||
|
||||
ProbedItem* OverflowBufferStart() const {
|
||||
// We reuse GrowthInfo memory as well.
|
||||
return AlignToNextItem(control_ - ControlOffset(/*has_infoz=*/false));
|
||||
return AlignToNextItem(control_ - ControlOffset(/*has_infoz=*/false,
|
||||
/*has_growth_info=*/true));
|
||||
}
|
||||
|
||||
// Encodes item when previously allocated buffer is full.
|
||||
|
||||
@@ -989,10 +989,20 @@ constexpr size_t NumControlBytes(size_t capacity) {
|
||||
return IsSmallCapacity(capacity) ? 0 : capacity + 1 + NumClonedBytes();
|
||||
}
|
||||
|
||||
// Returns whether table with the given capacity has a GrowthInfo.
|
||||
constexpr bool HasGrowthInfoForCapacity(size_t capacity) {
|
||||
return !IsSmallCapacity(capacity);
|
||||
}
|
||||
|
||||
// Computes the offset from the start of the backing allocation of control.
|
||||
// infoz and growth_info are stored at the beginning of the backing array.
|
||||
constexpr size_t ControlOffset(bool has_infoz) {
|
||||
return (has_infoz ? sizeof(HashtablezInfoHandle) : 0) + sizeof(GrowthInfo);
|
||||
constexpr size_t ControlOffset(bool has_infoz, bool has_growth_info) {
|
||||
if (ABSL_PREDICT_FALSE(has_infoz)) {
|
||||
// We always allocate GrowthInfo for sampled tables to allow branchless
|
||||
// access to infoz pointer.
|
||||
return sizeof(HashtablezInfoHandle) + sizeof(GrowthInfo);
|
||||
}
|
||||
return has_growth_info ? sizeof(GrowthInfo) : 0;
|
||||
}
|
||||
|
||||
// Returns the offset of the next item after `offset` that is aligned to `align`
|
||||
@@ -1004,12 +1014,10 @@ constexpr size_t AlignUpTo(size_t offset, size_t align) {
|
||||
// Helper class for computing offsets and allocation size of hash set fields.
|
||||
class RawHashSetLayout {
|
||||
public:
|
||||
// TODO(b/413062340): maybe don't allocate growth info for capacity 1 tables.
|
||||
// Doing so may require additional branches/complexity so it might not be
|
||||
// worth it.
|
||||
explicit RawHashSetLayout(size_t capacity, size_t slot_size,
|
||||
size_t slot_align, bool has_infoz)
|
||||
: control_offset_(ControlOffset(has_infoz)),
|
||||
: control_offset_(
|
||||
ControlOffset(has_infoz, HasGrowthInfoForCapacity(capacity))),
|
||||
generation_offset_(control_offset_ + NumControlBytes(capacity)),
|
||||
slot_offset_(
|
||||
AlignUpTo(generation_offset_ + NumGenerationBytes(), slot_align)),
|
||||
@@ -1240,7 +1248,7 @@ class CommonFields : public CommonFieldsGenerationInfo {
|
||||
size_t growth_left() const { return growth_info().GetGrowthLeft(); }
|
||||
|
||||
GrowthInfo& growth_info() {
|
||||
ABSL_SWISSTABLE_ASSERT(!is_small());
|
||||
ABSL_SWISSTABLE_ASSERT(HasGrowthInfoForCapacity(capacity()));
|
||||
return GetGrowthInfoFromControl(control());
|
||||
}
|
||||
GrowthInfo growth_info() const {
|
||||
@@ -1259,7 +1267,8 @@ class CommonFields : public CommonFieldsGenerationInfo {
|
||||
reinterpret_cast<uintptr_t>(control()) % alignof(size_t) == 0);
|
||||
ABSL_SWISSTABLE_ASSERT(has_infoz());
|
||||
return reinterpret_cast<HashtablezInfoHandle*>(
|
||||
control() - ControlOffset(/*has_infoz=*/true));
|
||||
control() - ControlOffset(/*has_infoz=*/true,
|
||||
HasGrowthInfoForCapacity(capacity())));
|
||||
}
|
||||
|
||||
HashtablezInfoHandle infoz() {
|
||||
|
||||
@@ -2772,6 +2772,18 @@ TYPED_TEST(SooTest, HintInsert) {
|
||||
EXPECT_TRUE(node); // NOLINT(bugprone-use-after-move)
|
||||
}
|
||||
|
||||
TYPED_TEST(SooTest, RehashZeroForSmallTable) {
|
||||
TypeParam t{0};
|
||||
EXPECT_EQ(t.capacity(), 1);
|
||||
t.rehash(0);
|
||||
EXPECT_EQ(t.capacity(), 1);
|
||||
EXPECT_TRUE(t.contains(0));
|
||||
t.insert(1);
|
||||
EXPECT_EQ(t.capacity(), NextCapacity(1));
|
||||
EXPECT_TRUE(t.contains(0));
|
||||
EXPECT_TRUE(t.contains(1));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T MakeSimpleTable(size_t size, bool do_reserve) {
|
||||
T t;
|
||||
|
||||
Reference in New Issue
Block a user