sharded_cache.cc 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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. #include "cache/sharded_cache.h"
  10. #include <string>
  11. #include "util/mutexlock.h"
  12. namespace ROCKSDB_NAMESPACE {
  13. ShardedCache::ShardedCache(size_t capacity, int num_shard_bits,
  14. bool strict_capacity_limit,
  15. std::shared_ptr<MemoryAllocator> allocator)
  16. : Cache(std::move(allocator)),
  17. num_shard_bits_(num_shard_bits),
  18. capacity_(capacity),
  19. strict_capacity_limit_(strict_capacity_limit),
  20. last_id_(1) {}
  21. void ShardedCache::SetCapacity(size_t capacity) {
  22. int num_shards = 1 << num_shard_bits_;
  23. const size_t per_shard = (capacity + (num_shards - 1)) / num_shards;
  24. MutexLock l(&capacity_mutex_);
  25. for (int s = 0; s < num_shards; s++) {
  26. GetShard(s)->SetCapacity(per_shard);
  27. }
  28. capacity_ = capacity;
  29. }
  30. void ShardedCache::SetStrictCapacityLimit(bool strict_capacity_limit) {
  31. int num_shards = 1 << num_shard_bits_;
  32. MutexLock l(&capacity_mutex_);
  33. for (int s = 0; s < num_shards; s++) {
  34. GetShard(s)->SetStrictCapacityLimit(strict_capacity_limit);
  35. }
  36. strict_capacity_limit_ = strict_capacity_limit;
  37. }
  38. Status ShardedCache::Insert(const Slice& key, void* value, size_t charge,
  39. void (*deleter)(const Slice& key, void* value),
  40. Handle** handle, Priority priority) {
  41. uint32_t hash = HashSlice(key);
  42. return GetShard(Shard(hash))
  43. ->Insert(key, hash, value, charge, deleter, handle, priority);
  44. }
  45. Cache::Handle* ShardedCache::Lookup(const Slice& key, Statistics* /*stats*/) {
  46. uint32_t hash = HashSlice(key);
  47. return GetShard(Shard(hash))->Lookup(key, hash);
  48. }
  49. bool ShardedCache::Ref(Handle* handle) {
  50. uint32_t hash = GetHash(handle);
  51. return GetShard(Shard(hash))->Ref(handle);
  52. }
  53. bool ShardedCache::Release(Handle* handle, bool force_erase) {
  54. uint32_t hash = GetHash(handle);
  55. return GetShard(Shard(hash))->Release(handle, force_erase);
  56. }
  57. void ShardedCache::Erase(const Slice& key) {
  58. uint32_t hash = HashSlice(key);
  59. GetShard(Shard(hash))->Erase(key, hash);
  60. }
  61. uint64_t ShardedCache::NewId() {
  62. return last_id_.fetch_add(1, std::memory_order_relaxed);
  63. }
  64. size_t ShardedCache::GetCapacity() const {
  65. MutexLock l(&capacity_mutex_);
  66. return capacity_;
  67. }
  68. bool ShardedCache::HasStrictCapacityLimit() const {
  69. MutexLock l(&capacity_mutex_);
  70. return strict_capacity_limit_;
  71. }
  72. size_t ShardedCache::GetUsage() const {
  73. // We will not lock the cache when getting the usage from shards.
  74. int num_shards = 1 << num_shard_bits_;
  75. size_t usage = 0;
  76. for (int s = 0; s < num_shards; s++) {
  77. usage += GetShard(s)->GetUsage();
  78. }
  79. return usage;
  80. }
  81. size_t ShardedCache::GetUsage(Handle* handle) const {
  82. return GetCharge(handle);
  83. }
  84. size_t ShardedCache::GetPinnedUsage() const {
  85. // We will not lock the cache when getting the usage from shards.
  86. int num_shards = 1 << num_shard_bits_;
  87. size_t usage = 0;
  88. for (int s = 0; s < num_shards; s++) {
  89. usage += GetShard(s)->GetPinnedUsage();
  90. }
  91. return usage;
  92. }
  93. void ShardedCache::ApplyToAllCacheEntries(void (*callback)(void*, size_t),
  94. bool thread_safe) {
  95. int num_shards = 1 << num_shard_bits_;
  96. for (int s = 0; s < num_shards; s++) {
  97. GetShard(s)->ApplyToAllCacheEntries(callback, thread_safe);
  98. }
  99. }
  100. void ShardedCache::EraseUnRefEntries() {
  101. int num_shards = 1 << num_shard_bits_;
  102. for (int s = 0; s < num_shards; s++) {
  103. GetShard(s)->EraseUnRefEntries();
  104. }
  105. }
  106. std::string ShardedCache::GetPrintableOptions() const {
  107. std::string ret;
  108. ret.reserve(20000);
  109. const int kBufferSize = 200;
  110. char buffer[kBufferSize];
  111. {
  112. MutexLock l(&capacity_mutex_);
  113. snprintf(buffer, kBufferSize, " capacity : %" ROCKSDB_PRIszt "\n",
  114. capacity_);
  115. ret.append(buffer);
  116. snprintf(buffer, kBufferSize, " num_shard_bits : %d\n", num_shard_bits_);
  117. ret.append(buffer);
  118. snprintf(buffer, kBufferSize, " strict_capacity_limit : %d\n",
  119. strict_capacity_limit_);
  120. ret.append(buffer);
  121. }
  122. snprintf(buffer, kBufferSize, " memory_allocator : %s\n",
  123. memory_allocator() ? memory_allocator()->Name() : "None");
  124. ret.append(buffer);
  125. ret.append(GetShard(0)->GetPrintableOptions());
  126. return ret;
  127. }
  128. int GetDefaultCacheShardBits(size_t capacity) {
  129. int num_shard_bits = 0;
  130. size_t min_shard_size = 512L * 1024L; // Every shard is at least 512KB.
  131. size_t num_shards = capacity / min_shard_size;
  132. while (num_shards >>= 1) {
  133. if (++num_shard_bits >= 6) {
  134. // No more than 6.
  135. return num_shard_bits;
  136. }
  137. }
  138. return num_shard_bits;
  139. }
  140. } // namespace ROCKSDB_NAMESPACE