Commit d87dc03c by Vitaly Goldshteyn Committed by Copybara-Service

Optimize `prepare_insert`, when resize happens. It removes single unnecessary…

Optimize `prepare_insert`, when resize happens. It removes single unnecessary probing before resize that is beneficial for small tables the most.

PiperOrigin-RevId: 609547787
Change-Id: If6584919b4c93945ea078b1c1a9f57b355dce924
parent 0e72e54f
...@@ -1623,8 +1623,10 @@ class HashSetResizeHelper { ...@@ -1623,8 +1623,10 @@ class HashSetResizeHelper {
old_capacity_(c.capacity()), old_capacity_(c.capacity()),
had_infoz_(c.has_infoz()) {} had_infoz_(c.has_infoz()) {}
// Optimized for small groups version of `find_first_non_full` applicable // Optimized for small groups version of `find_first_non_full`.
// only right after calling `raw_hash_set::resize`. // Beneficial only right after calling `raw_hash_set::resize`.
// It is safe to call in case capacity is big or was not changed, but there
// will be no performance benefit.
// It has implicit assumption that `resize` will call // It has implicit assumption that `resize` will call
// `GrowSizeIntoSingleGroup*` in case `IsGrowingIntoSingleGroupApplicable`. // `GrowSizeIntoSingleGroup*` in case `IsGrowingIntoSingleGroupApplicable`.
// Falls back to `find_first_non_full` in case of big groups, so it is // Falls back to `find_first_non_full` in case of big groups, so it is
...@@ -3244,21 +3246,21 @@ class raw_hash_set { ...@@ -3244,21 +3246,21 @@ class raw_hash_set {
const size_t cap = capacity(); const size_t cap = capacity();
resize(growth_left() > 0 ? cap : NextCapacity(cap)); resize(growth_left() > 0 ? cap : NextCapacity(cap));
} }
auto target = find_first_non_full(common(), hash); FindInfo target;
if (!rehash_for_bug_detection && if (!rehash_for_bug_detection && ABSL_PREDICT_FALSE(growth_left() == 0)) {
ABSL_PREDICT_FALSE(growth_left() == 0 && const size_t old_capacity = capacity();
!IsDeleted(control()[target.offset]))) {
size_t old_capacity = capacity();
rehash_and_grow_if_necessary(); rehash_and_grow_if_necessary();
// NOTE: It is safe to use `FindFirstNonFullAfterResize`. // NOTE: It is safe to use `FindFirstNonFullAfterResize` after
// `FindFirstNonFullAfterResize` must be called right after resize. // `rehash_and_grow_if_necessary`, whether capacity changes or not.
// `rehash_and_grow_if_necessary` may *not* call `resize` // `rehash_and_grow_if_necessary` may *not* call `resize`
// and perform `drop_deletes_without_resize` instead. But this // and perform `drop_deletes_without_resize` instead. But this
// could happen only on big tables. // could happen only on big tables and will not change capacity.
// For big tables `FindFirstNonFullAfterResize` will always // For big tables `FindFirstNonFullAfterResize` will always
// fallback to normal `find_first_non_full`, so it is safe to use it. // fallback to normal `find_first_non_full`.
target = HashSetResizeHelper::FindFirstNonFullAfterResize( target = HashSetResizeHelper::FindFirstNonFullAfterResize(
common(), old_capacity, hash); common(), old_capacity, hash);
} else {
target = find_first_non_full(common(), hash);
} }
common().increment_size(); common().increment_size();
set_growth_left(growth_left() - IsEmpty(control()[target.offset])); set_growth_left(growth_left() - IsEmpty(control()[target.offset]));
......
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