dynamic_bloom.cc 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  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. #include "dynamic_bloom.h"
  6. #include <algorithm>
  7. #include "memory/allocator.h"
  8. #include "port/port.h"
  9. #include "rocksdb/slice.h"
  10. #include "util/hash.h"
  11. namespace ROCKSDB_NAMESPACE {
  12. namespace {
  13. uint32_t roundUpToPow2(uint32_t x) {
  14. uint32_t rv = 1;
  15. while (rv < x) {
  16. rv <<= 1;
  17. }
  18. return rv;
  19. }
  20. }
  21. DynamicBloom::DynamicBloom(Allocator* allocator, uint32_t total_bits,
  22. uint32_t num_probes, size_t huge_page_tlb_size,
  23. Logger* logger)
  24. // Round down, except round up with 1
  25. : kNumDoubleProbes((num_probes + (num_probes == 1)) / 2) {
  26. assert(num_probes % 2 == 0); // limitation of current implementation
  27. assert(num_probes <= 10); // limitation of current implementation
  28. assert(kNumDoubleProbes > 0);
  29. // Determine how much to round off + align by so that x ^ i (that's xor) is
  30. // a valid u64 index if x is a valid u64 index and 0 <= i < kNumDoubleProbes.
  31. uint32_t block_bytes = /*bytes/u64*/ 8 *
  32. /*u64s*/ std::max(1U, roundUpToPow2(kNumDoubleProbes));
  33. uint32_t block_bits = block_bytes * 8;
  34. uint32_t blocks = (total_bits + block_bits - 1) / block_bits;
  35. uint32_t sz = blocks * block_bytes;
  36. kLen = sz / /*bytes/u64*/ 8;
  37. assert(kLen > 0);
  38. #ifndef NDEBUG
  39. for (uint32_t i = 0; i < kNumDoubleProbes; ++i) {
  40. // Ensure probes starting at last word are in range
  41. assert(((kLen - 1) ^ i) < kLen);
  42. }
  43. #endif
  44. // Padding to correct for allocation not originally aligned on block_bytes
  45. // boundary
  46. sz += block_bytes - 1;
  47. assert(allocator);
  48. char* raw = allocator->AllocateAligned(sz, huge_page_tlb_size, logger);
  49. memset(raw, 0, sz);
  50. auto block_offset = reinterpret_cast<uintptr_t>(raw) % block_bytes;
  51. if (block_offset > 0) {
  52. // Align on block_bytes boundary
  53. raw += block_bytes - block_offset;
  54. }
  55. static_assert(sizeof(std::atomic<uint64_t>) == sizeof(uint64_t),
  56. "Expecting zero-space-overhead atomic");
  57. data_ = reinterpret_cast<std::atomic<uint64_t>*>(raw);
  58. }
  59. } // namespace ROCKSDB_NAMESPACE