Skip to content

Commit 7bf6d79

Browse files
goldvitalycopybara-github
authored andcommitted
Use weaker mixing for absl::Hash for types that mix their sizes.
When a container or a string is mixed, size is only supplementary data. We are still mixing size to avoid hash expansion to be a suffix of one another. Mixing is done by addition `size + Seed()`. `+ Seed()` is needed to make an empty string to change the hash state. We assume that `Seed()` is already loaded to some register. Addition would modify low bits that will be spread with data mixing later. We considered the following optimization. Mix the size at the beginning in order to improve the dependency graph. Mixing would happen in parallel with reading strings data. It's not feasible because absl::Hash API requires that hash expansions can't be suffixes of each other. ``` name old CYCLES/op new CYCLES/op delta BM_latency_AbslHash_String3 27.2 ± 0% 21.5 ± 0% -21.08% (p=0.000 n=52+52) BM_latency_AbslHash_String5 28.1 ± 8% 22.3 ±11% -20.70% (p=0.000 n=57+57) BM_latency_AbslHash_String9 27.7 ± 9% 22.2 ±17% -19.77% (p=0.000 n=56+57) BM_latency_AbslHash_String17 25.9 ± 5% 21.2 ±23% -18.02% (p=0.000 n=57+54) BM_latency_AbslHash_String33 28.0 ± 5% 22.5 ± 4% -19.69% (p=0.000 n=54+54) BM_latency_AbslHash_String65 37.9 ± 8% 32.2 ±10% -15.19% (p=0.000 n=52+53) BM_latency_AbslHash_String257 57.1 ± 8% 52.0 ±10% -8.88% (p=0.000 n=52+54) ``` PiperOrigin-RevId: 750151406 Change-Id: I2245bad4906960d9236bea671738a218a85eb1af
1 parent 8b2b78b commit 7bf6d79

21 files changed

+194
-35
lines changed

CMake/AbseilDll.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ set(ABSL_INTERNAL_DLL_FILES
162162
"hash/internal/spy_hash_state.h"
163163
"hash/internal/low_level_hash.h"
164164
"hash/internal/low_level_hash.cc"
165+
"hash/internal/weakly_mixed_integer.h"
165166
"log/absl_check.h"
166167
"log/absl_log.h"
167168
"log/absl_vlog_is_on.h"

absl/container/BUILD.bazel

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ cc_library(
7272
"//absl/base:dynamic_annotations",
7373
"//absl/base:iterator_traits_internal",
7474
"//absl/base:throw_delegate",
75+
"//absl/hash:weakly_mixed_integer",
7576
"//absl/memory",
7677
],
7778
)
@@ -148,6 +149,7 @@ cc_library(
148149
"//absl/base:core_headers",
149150
"//absl/base:iterator_traits_internal",
150151
"//absl/base:throw_delegate",
152+
"//absl/hash:weakly_mixed_integer",
151153
"//absl/memory",
152154
"//absl/meta:type_traits",
153155
],
@@ -740,6 +742,7 @@ cc_library(
740742
"//absl/base:raw_logging_internal",
741743
"//absl/functional:function_ref",
742744
"//absl/hash",
745+
"//absl/hash:weakly_mixed_integer",
743746
"//absl/memory",
744747
"//absl/meta:type_traits",
745748
"//absl/numeric:bits",
@@ -1086,6 +1089,7 @@ cc_library(
10861089
"//absl/base:core_headers",
10871090
"//absl/base:raw_logging_internal",
10881091
"//absl/base:throw_delegate",
1092+
"//absl/hash:weakly_mixed_integer",
10891093
"//absl/memory",
10901094
"//absl/meta:type_traits",
10911095
"//absl/strings",

absl/container/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ absl_cc_library(
4141
absl::strings
4242
absl::throw_delegate
4343
absl::type_traits
44+
absl::weakly_mixed_integer
4445
)
4546

4647
# Internal-only target, do not depend on directly.
@@ -134,6 +135,7 @@ absl_cc_library(
134135
absl::iterator_traits_internal
135136
absl::throw_delegate
136137
absl::memory
138+
absl::weakly_mixed_integer
137139
PUBLIC
138140
)
139141

@@ -202,6 +204,7 @@ absl_cc_library(
202204
absl::throw_delegate
203205
absl::memory
204206
absl::type_traits
207+
absl::weakly_mixed_integer
205208
PUBLIC
206209
)
207210

@@ -790,6 +793,7 @@ absl_cc_library(
790793
absl::prefetch
791794
absl::raw_logging_internal
792795
absl::utility
796+
absl::weakly_mixed_integer
793797
PUBLIC
794798
)
795799

absl/container/fixed_array.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "absl/base/optimization.h"
5151
#include "absl/base/port.h"
5252
#include "absl/container/internal/compressed_tuple.h"
53+
#include "absl/hash/internal/weakly_mixed_integer.h"
5354
#include "absl/memory/memory.h"
5455

5556
namespace absl {
@@ -392,7 +393,7 @@ class ABSL_ATTRIBUTE_WARN_UNUSED FixedArray {
392393
template <typename H>
393394
friend H AbslHashValue(H h, const FixedArray& v) {
394395
return H::combine(H::combine_contiguous(std::move(h), v.data(), v.size()),
395-
v.size());
396+
hash_internal::WeaklyMixedInteger{v.size()});
396397
}
397398

398399
private:

absl/container/inlined_vector.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include "absl/base/optimization.h"
5454
#include "absl/base/port.h"
5555
#include "absl/container/internal/inlined_vector.h"
56+
#include "absl/hash/internal/weakly_mixed_integer.h"
5657
#include "absl/memory/memory.h"
5758
#include "absl/meta/type_traits.h"
5859

@@ -1008,7 +1009,8 @@ bool operator>=(const absl::InlinedVector<T, N, A>& a,
10081009
template <typename H, typename T, size_t N, typename A>
10091010
H AbslHashValue(H h, const absl::InlinedVector<T, N, A>& a) {
10101011
auto size = a.size();
1011-
return H::combine(H::combine_contiguous(std::move(h), a.data(), size), size);
1012+
return H::combine(H::combine_contiguous(std::move(h), a.data(), size),
1013+
hash_internal::WeaklyMixedInteger{size});
10121014
}
10131015

10141016
ABSL_NAMESPACE_END

absl/container/internal/btree_container.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "absl/base/internal/throw_delegate.h"
2626
#include "absl/container/internal/btree.h" // IWYU pragma: export
2727
#include "absl/container/internal/common.h"
28+
#include "absl/hash/internal/weakly_mixed_integer.h"
2829
#include "absl/memory/memory.h"
2930
#include "absl/meta/type_traits.h"
3031

@@ -267,7 +268,8 @@ class btree_container {
267268
for (const auto &v : b) {
268269
h = State::combine(std::move(h), v);
269270
}
270-
return State::combine(std::move(h), b.size());
271+
return State::combine(std::move(h),
272+
hash_internal::WeaklyMixedInteger{b.size()});
271273
}
272274

273275
protected:

absl/container/internal/raw_hash_set.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@
214214
#include "absl/container/internal/hashtablez_sampler.h"
215215
#include "absl/functional/function_ref.h"
216216
#include "absl/hash/hash.h"
217+
#include "absl/hash/internal/weakly_mixed_integer.h"
217218
#include "absl/memory/memory.h"
218219
#include "absl/meta/type_traits.h"
219220
#include "absl/numeric/bits.h"
@@ -2985,7 +2986,7 @@ class raw_hash_set {
29852986
H>::type
29862987
AbslHashValue(H h, const raw_hash_set& s) {
29872988
return H::combine(H::combine_unordered(std::move(h), s.begin(), s.end()),
2988-
s.size());
2989+
hash_internal::WeaklyMixedInteger{s.size()});
29892990
}
29902991

29912992
friend void swap(raw_hash_set& a,

absl/hash/BUILD.bazel

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ cc_library(
4444
deps = [
4545
":city",
4646
":low_level_hash",
47+
":weakly_mixed_integer",
4748
"//absl/base:config",
4849
"//absl/base:core_headers",
4950
"//absl/base:endian",
@@ -151,6 +152,7 @@ cc_library(
151152
visibility = ["//visibility:private"],
152153
deps = [
153154
":hash",
155+
":weakly_mixed_integer",
154156
"//absl/strings",
155157
"//absl/strings:str_format",
156158
],
@@ -199,6 +201,21 @@ cc_library(
199201
],
200202
)
201203

204+
cc_library(
205+
name = "weakly_mixed_integer",
206+
hdrs = ["internal/weakly_mixed_integer.h"],
207+
copts = ABSL_DEFAULT_COPTS,
208+
linkopts = ABSL_DEFAULT_LINKOPTS,
209+
visibility = [
210+
"//absl/container:__pkg__",
211+
"//absl/strings:__pkg__",
212+
"//absl/types:__pkg__",
213+
],
214+
deps = [
215+
"//absl/base:config",
216+
],
217+
)
218+
202219
cc_test(
203220
name = "low_level_hash_test",
204221
srcs = ["internal/low_level_hash_test.cc"],

absl/hash/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ absl_cc_library(
3939
absl::variant
4040
absl::utility
4141
absl::low_level_hash
42+
absl::weakly_mixed_integer
4243
PUBLIC
4344
)
4445

@@ -119,6 +120,7 @@ absl_cc_library(
119120
absl::hash
120121
absl::strings
121122
absl::str_format
123+
absl::weakly_mixed_integer
122124
TESTONLY
123125
PUBLIC
124126
)
@@ -169,6 +171,18 @@ absl_cc_library(
169171
absl::prefetch
170172
)
171173

174+
# Internal-only target, do not depend on directly.
175+
absl_cc_library(
176+
NAME
177+
weakly_mixed_integer
178+
HDRS
179+
"internal/weakly_mixed_integer.h"
180+
COPTS
181+
${ABSL_DEFAULT_COPTS}
182+
DEPS
183+
absl::config
184+
)
185+
172186
absl_cc_test(
173187
NAME
174188
low_level_hash_test

absl/hash/hash.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
#include "absl/base/config.h"
8888
#include "absl/functional/function_ref.h"
8989
#include "absl/hash/internal/hash.h"
90+
#include "absl/hash/internal/weakly_mixed_integer.h"
9091
#include "absl/meta/type_traits.h"
9192

9293
namespace absl {
@@ -356,6 +357,12 @@ class HashState : public hash_internal::HashStateBase<HashState> {
356357
hash_state.combine_contiguous_(hash_state.state_, first, size);
357358
return hash_state;
358359
}
360+
361+
static HashState combine_weakly_mixed_integer(
362+
HashState hash_state, hash_internal::WeaklyMixedInteger value) {
363+
hash_state.combine_weakly_mixed_integer_(hash_state.state_, value);
364+
return hash_state;
365+
}
359366
using HashState::HashStateBase::combine_contiguous;
360367

361368
private:
@@ -371,6 +378,13 @@ class HashState : public hash_internal::HashStateBase<HashState> {
371378
state = T::combine_contiguous(std::move(state), first, size);
372379
}
373380

381+
template <typename T>
382+
static void CombineWeaklyMixedIntegerImpl(
383+
void* p, hash_internal::WeaklyMixedInteger value) {
384+
T& state = *static_cast<T*>(p);
385+
state = T::combine_weakly_mixed_integer(std::move(state), value);
386+
}
387+
374388
static HashState combine_raw(HashState hash_state, uint64_t value) {
375389
hash_state.combine_raw_(hash_state.state_, value);
376390
return hash_state;
@@ -385,6 +399,7 @@ class HashState : public hash_internal::HashStateBase<HashState> {
385399
template <typename T>
386400
void Init(T* state) {
387401
state_ = state;
402+
combine_weakly_mixed_integer_ = &CombineWeaklyMixedIntegerImpl<T>;
388403
combine_contiguous_ = &CombineContiguousImpl<T>;
389404
combine_raw_ = &CombineRawImpl<T>;
390405
run_combine_unordered_ = &RunCombineUnorderedImpl<T>;
@@ -424,6 +439,7 @@ class HashState : public hash_internal::HashStateBase<HashState> {
424439
// Do not erase an already erased state.
425440
void Init(HashState* state) {
426441
state_ = state->state_;
442+
combine_weakly_mixed_integer_ = state->combine_weakly_mixed_integer_;
427443
combine_contiguous_ = state->combine_contiguous_;
428444
combine_raw_ = state->combine_raw_;
429445
run_combine_unordered_ = state->run_combine_unordered_;
@@ -435,6 +451,8 @@ class HashState : public hash_internal::HashStateBase<HashState> {
435451
}
436452

437453
void* state_;
454+
void (*combine_weakly_mixed_integer_)(
455+
void*, absl::hash_internal::WeaklyMixedInteger);
438456
void (*combine_contiguous_)(void*, const unsigned char*, size_t);
439457
void (*combine_raw_)(void*, uint64_t);
440458
HashState (*run_combine_unordered_)(

0 commit comments

Comments
 (0)