diff options
author | Vitaly Goldshteyn <goldvitaly@google.com> | 2024-06-20 13:43:52 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2024-06-20 13:45:02 -0700 |
commit | 10ac811f7c3720761c0fa0cd2b3fe92116b89420 (patch) | |
tree | 045af5b9491c5ebddf445a5921adaacc99d8d183 /absl/container/flat_hash_map.h | |
parent | 93763764d7554882db31364d822cb9fb924ca594 (diff) |
Create `absl::container_internal::c_for_each_fast` for SwissTable.
This function is aimed to achieve faster iteration through the entire hash table.
It is not ready to be used by the public and stays in `container_internal` namespace.
Differences with `absl::c_for_each`:
1. No guarantees on order of iteration. Although for the hash table it is partially not guaranteed already. But we do not even guarantee that it is the same order as in the for loop range. De facto, the order is the same at the moment.
2. No mutating reentrance is allowed. Most notably erasing from the hash_table is not allowed.
Based on microbenchmarks, there are following conclusions:
1. c_for_each_fast is clearly faster on big tables with 20-60% speedup.
2. Microbenchmarks show regression on a full small table without any empty slots.
We should avoid recommending that for small tables.
3. It seems reasonable to use `c_for_each_fast` in places, where `skip_empty_or_deleted` has significant GCU usage. `skip_empty_or_deleted` usage signals that there are "gaps" between elements, so `c_for_each_fast` should be an improvement.
PiperOrigin-RevId: 645142512
Change-Id: I279886b8c8b2545504c2bf7e037d27b2545e044d
Diffstat (limited to 'absl/container/flat_hash_map.h')
-rw-r--r-- | absl/container/flat_hash_map.h | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/absl/container/flat_hash_map.h b/absl/container/flat_hash_map.h index 3eae404f..ebd9ed67 100644 --- a/absl/container/flat_hash_map.h +++ b/absl/container/flat_hash_map.h @@ -43,6 +43,7 @@ #include "absl/container/hash_container_defaults.h" #include "absl/container/internal/container_memory.h" #include "absl/container/internal/raw_hash_map.h" // IWYU pragma: export +#include "absl/meta/type_traits.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -575,6 +576,38 @@ typename flat_hash_map<K, V, H, E, A>::size_type erase_if( namespace container_internal { +// c_for_each_fast(flat_hash_map<>, Function) +// +// Container-based version of the <algorithm> `std::for_each()` function to +// apply a function to a container's elements. +// There is no guarantees on the order of the function calls. +// Erasure and/or insertion of elements in the function is not allowed. +template <typename K, typename V, typename H, typename E, typename A, + typename Function> +decay_t<Function> c_for_each_fast(const flat_hash_map<K, V, H, E, A>& c, + Function&& f) { + container_internal::ForEach(f, &c); + return f; +} +template <typename K, typename V, typename H, typename E, typename A, + typename Function> +decay_t<Function> c_for_each_fast(flat_hash_map<K, V, H, E, A>& c, + Function&& f) { + container_internal::ForEach(f, &c); + return f; +} +template <typename K, typename V, typename H, typename E, typename A, + typename Function> +decay_t<Function> c_for_each_fast(flat_hash_map<K, V, H, E, A>&& c, + Function&& f) { + container_internal::ForEach(f, &c); + return f; +} + +} // namespace container_internal + +namespace container_internal { + template <class K, class V> struct FlatHashMapPolicy { using slot_policy = container_internal::map_slot_policy<K, V>; |