/src/rocksdb/cache/sharded_cache.cc
Line | Count | Source |
1 | | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
2 | | // This source code is licensed under both the GPLv2 (found in the |
3 | | // COPYING file in the root directory) and Apache 2.0 License |
4 | | // (found in the LICENSE.Apache file in the root directory). |
5 | | // |
6 | | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. |
7 | | // Use of this source code is governed by a BSD-style license that can be |
8 | | // found in the LICENSE file. See the AUTHORS file for names of contributors. |
9 | | |
10 | | #include "cache/sharded_cache.h" |
11 | | |
12 | | #include <algorithm> |
13 | | #include <cstdint> |
14 | | #include <memory> |
15 | | |
16 | | #include "env/unique_id_gen.h" |
17 | | #include "rocksdb/env.h" |
18 | | #include "util/hash.h" |
19 | | #include "util/math.h" |
20 | | #include "util/mutexlock.h" |
21 | | |
22 | | namespace ROCKSDB_NAMESPACE { |
23 | | namespace { |
24 | | // The generated seeds must fit in 31 bits so that |
25 | | // ShardedCacheOptions::hash_seed can be set to it explicitly, for |
26 | | // diagnostic/debugging purposes. |
27 | | constexpr uint32_t kSeedMask = 0x7fffffff; |
28 | 657k | uint32_t DetermineSeed(int32_t hash_seed_option) { |
29 | 657k | if (hash_seed_option >= 0) { |
30 | | // User-specified exact seed |
31 | 49.7k | return static_cast<uint32_t>(hash_seed_option); |
32 | 49.7k | } |
33 | 607k | static SemiStructuredUniqueIdGen gen; |
34 | 607k | if (hash_seed_option == ShardedCacheOptions::kHostHashSeed) { |
35 | 607k | std::string hostname; |
36 | 607k | Status s = Env::Default()->GetHostNameString(&hostname); |
37 | 607k | if (s.ok()) { |
38 | 607k | return GetSliceHash(hostname) & kSeedMask; |
39 | 607k | } else { |
40 | | // Fall back on something stable within the process. |
41 | 0 | return BitwiseAnd(gen.GetBaseUpper(), kSeedMask); |
42 | 0 | } |
43 | 607k | } else { |
44 | | // for kQuasiRandomHashSeed and fallback |
45 | 0 | uint32_t val = gen.GenerateNext<uint32_t>() & kSeedMask; |
46 | | // Perform some 31-bit bijective transformations so that we get |
47 | | // quasirandom, not just incrementing. (An incrementing seed from a |
48 | | // random starting point would be fine, but hard to describe in a name.) |
49 | | // See https://en.wikipedia.org/wiki/Quasirandom and using a murmur-like |
50 | | // transformation here for our bijection in the lower 31 bits. |
51 | | // See https://en.wikipedia.org/wiki/MurmurHash |
52 | 0 | val *= /*31-bit prime*/ 1150630961; |
53 | 0 | val ^= (val & kSeedMask) >> 17; |
54 | 0 | val *= /*31-bit prime*/ 1320603883; |
55 | 0 | return val & kSeedMask; |
56 | 0 | } |
57 | 607k | } |
58 | | } // namespace |
59 | | |
60 | | ShardedCacheBase::ShardedCacheBase(const ShardedCacheOptions& opts) |
61 | 657k | : Cache(opts.memory_allocator), |
62 | 657k | last_id_(1), |
63 | 657k | shard_mask_((uint32_t{1} << opts.num_shard_bits) - 1), |
64 | 657k | hash_seed_(DetermineSeed(opts.hash_seed)), |
65 | 657k | strict_capacity_limit_(opts.strict_capacity_limit), |
66 | 657k | capacity_(opts.capacity) {} |
67 | | |
68 | 657k | size_t ShardedCacheBase::ComputePerShardCapacity(size_t capacity) const { |
69 | 657k | uint32_t num_shards = GetNumShards(); |
70 | 657k | return (capacity + (num_shards - 1)) / num_shards; |
71 | 657k | } |
72 | | |
73 | 657k | size_t ShardedCacheBase::GetPerShardCapacity() const { |
74 | 657k | return ComputePerShardCapacity(GetCapacity()); |
75 | 657k | } |
76 | | |
77 | 10.0k | uint64_t ShardedCacheBase::NewId() { |
78 | 10.0k | return last_id_.fetch_add(1, std::memory_order_relaxed); |
79 | 10.0k | } |
80 | | |
81 | 1.13M | size_t ShardedCacheBase::GetCapacity() const { |
82 | 1.13M | MutexLock l(&config_mutex_); |
83 | 1.13M | return capacity_; |
84 | 1.13M | } |
85 | | |
86 | 0 | Status ShardedCacheBase::GetSecondaryCacheCapacity(size_t& size) const { |
87 | 0 | size = 0; |
88 | 0 | return Status::OK(); |
89 | 0 | } |
90 | | |
91 | 0 | Status ShardedCacheBase::GetSecondaryCachePinnedUsage(size_t& size) const { |
92 | 0 | size = 0; |
93 | 0 | return Status::OK(); |
94 | 0 | } |
95 | | |
96 | 0 | bool ShardedCacheBase::HasStrictCapacityLimit() const { |
97 | 0 | MutexLock l(&config_mutex_); |
98 | 0 | return strict_capacity_limit_; |
99 | 0 | } |
100 | | |
101 | 19.1k | size_t ShardedCacheBase::GetUsage(Handle* handle) const { |
102 | 19.1k | return GetCharge(handle); |
103 | 19.1k | } |
104 | | |
105 | 100k | std::string ShardedCacheBase::GetPrintableOptions() const { |
106 | 100k | std::string ret; |
107 | 100k | ret.reserve(20000); |
108 | 100k | const int kBufferSize = 200; |
109 | 100k | char buffer[kBufferSize]; |
110 | 100k | { |
111 | 100k | MutexLock l(&config_mutex_); |
112 | 100k | snprintf(buffer, kBufferSize, " capacity : %" ROCKSDB_PRIszt "\n", |
113 | 100k | capacity_); |
114 | 100k | ret.append(buffer); |
115 | 100k | snprintf(buffer, kBufferSize, " num_shard_bits : %d\n", |
116 | 100k | GetNumShardBits()); |
117 | 100k | ret.append(buffer); |
118 | 100k | snprintf(buffer, kBufferSize, " strict_capacity_limit : %d\n", |
119 | 100k | strict_capacity_limit_); |
120 | 100k | ret.append(buffer); |
121 | 100k | } |
122 | 100k | snprintf(buffer, kBufferSize, " memory_allocator : %s\n", |
123 | 100k | memory_allocator() ? memory_allocator()->Name() : "None"); |
124 | 100k | ret.append(buffer); |
125 | 100k | AppendPrintableOptions(ret); |
126 | 100k | return ret; |
127 | 100k | } |
128 | | |
129 | 607k | int GetDefaultCacheShardBits(size_t capacity, size_t min_shard_size) { |
130 | 607k | int num_shard_bits = 0; |
131 | 607k | size_t num_shards = capacity / min_shard_size; |
132 | 607k | while (num_shards >>= 1) { |
133 | 0 | if (++num_shard_bits >= 6) { |
134 | | // No more than 6. |
135 | 0 | return num_shard_bits; |
136 | 0 | } |
137 | 0 | } |
138 | 607k | return num_shard_bits; |
139 | 607k | } |
140 | | |
141 | 100k | int ShardedCacheBase::GetNumShardBits() const { |
142 | 100k | return BitsSetToOne(shard_mask_); |
143 | 100k | } |
144 | | |
145 | 2.68M | uint32_t ShardedCacheBase::GetNumShards() const { return shard_mask_ + 1; } |
146 | | |
147 | | } // namespace ROCKSDB_NAMESPACE |