Skip to content
This repository was archived by the owner on Jul 31, 2023. It is now read-only.

Commit 3ea4b42

Browse files
author
Ian Sturdy
authored
Extract hash mixing logic into a common class. (#121)
1 parent a44fa1c commit 3ea4b42

5 files changed

Lines changed: 65 additions & 18 deletions

File tree

opencensus/common/internal/BUILD

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ licenses(["notice"]) # Apache 2.0
2020

2121
package(default_visibility = ["//opencensus:__subpackages__"])
2222

23+
cc_library(
24+
name = "hash_mix",
25+
hdrs = ["hash_mix.h"],
26+
copts = DEFAULT_COPTS,
27+
)
28+
2329
cc_library(
2430
name = "random_lib",
2531
srcs = ["random.cc"],
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2018, OpenCensus Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef OPENCENSUS_COMMON_INTERNAL_HASH_MIX_H_
16+
#define OPENCENSUS_COMMON_INTERNAL_HASH_MIX_H_
17+
18+
#include <cstddef>
19+
#include <limits>
20+
21+
namespace opencensus {
22+
namespace common {
23+
24+
// HashMix provides efficient mixing of hash values.
25+
class HashMix final {
26+
public:
27+
HashMix() : hash_(1) {}
28+
29+
// Mixes in another *hashed* value.
30+
void Mix(std::size_t hash) {
31+
// A multiplier that has been found to provide good mixing.
32+
constexpr std::size_t kMul = 0xdc3eb94af8ab4c93ULL;
33+
hash_ *= kMul;
34+
hash_ =
35+
((hash << 19) | (hash >> (std::numeric_limits<size_t>::digits - 19))) +
36+
hash;
37+
}
38+
39+
size_t get() const { return hash_; }
40+
41+
private:
42+
std::size_t hash_;
43+
};
44+
45+
} // namespace common
46+
} // namespace opencensus
47+
48+
#endif // OPENCENSUS_COMMON_INTERNAL_HASH_MIX_H_

opencensus/common/internal/string_vector_hash.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,22 @@
1616
#define OPENCENSUS_COMMON_INTERNAL_STRING_VECTOR_HASH_H_
1717

1818
#include <functional>
19-
#include <limits>
2019
#include <string>
2120
#include <vector>
2221

22+
#include "opencensus/common/internal/hash_mix.h"
23+
2324
namespace opencensus {
2425
namespace common {
2526

2627
struct StringVectorHash {
2728
std::size_t operator()(const std::vector<std::string>& container) const {
2829
std::hash<std::string> hasher;
29-
size_t hash = 1;
30+
HashMix mixer;
3031
for (const auto& elem : container) {
31-
static const size_t kMul = static_cast<size_t>(0xdc3eb94af8ab4c93ULL);
32-
hash *= kMul;
33-
hash = ((hash << 19) |
34-
(hash >> (std::numeric_limits<size_t>::digits - 19))) +
35-
hasher(elem);
32+
mixer.Mix(hasher(elem));
3633
}
37-
return hash;
34+
return mixer.get();
3835
}
3936
};
4037

opencensus/stats/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ cc_library(
9696
],
9797
copts = DEFAULT_COPTS,
9898
deps = [
99+
"//opencensus/common/internal:hash_mix",
99100
"//opencensus/common/internal:stats_object",
100101
"//opencensus/common/internal:string_vector_hash",
101102
"@com_google_absl//absl/base:core_headers",

opencensus/stats/internal/tag_set.cc

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <vector>
2222

2323
#include "absl/strings/string_view.h"
24+
#include "opencensus/common/internal/hash_mix.h"
2425

2526
namespace opencensus {
2627
namespace stats {
@@ -44,18 +45,12 @@ void TagSet::Initialize() {
4445
std::sort(tags_.begin(), tags_.end());
4546

4647
std::hash<std::string> hasher;
47-
hash_ = 1;
48+
common::HashMix mixer;
4849
for (const auto& tag : tags_) {
49-
static const size_t kMul = static_cast<size_t>(0xdc3eb94af8ab4c93ULL);
50-
hash_ *= kMul;
51-
hash_ = ((hash_ << 19) |
52-
(hash_ >> (std::numeric_limits<size_t>::digits - 19))) +
53-
hasher(tag.first);
54-
hash_ *= kMul;
55-
hash_ = ((hash_ << 19) |
56-
(hash_ >> (std::numeric_limits<size_t>::digits - 19))) +
57-
hasher(tag.second);
50+
mixer.Mix(hasher(tag.first));
51+
mixer.Mix(hasher(tag.second));
5852
}
53+
hash_ = mixer.get();
5954
}
6055

6156
std::size_t TagSet::Hash::operator()(const TagSet& tag_set) const {

0 commit comments

Comments
 (0)