From cd535c2280dea4c45b5138bce27870ff1c633d11 Mon Sep 17 00:00:00 2001 From: Kai Liu Date: Tue, 14 Jan 2014 21:30:13 -0800 Subject: [PATCH] Optimize MayContainHash() Summary: In latest leaf's, MayContainHash() consistently consumes 5%~7% CPU usage. I checked the code and did an experiment with/without inlining this method. In release mode, with `1024 * 1024 * 256` bits and `1024 * 512` entries, both call 2^30 MayContainHash() with distinctive parameters. As the result showed, this patch reduced the running time from 9.127 sec to 7.891 sec. Test Plan: make check Reviewers: sdong, haobo CC: leveldb Differential Revision: https://reviews.facebook.net/D15177 --- util/dynamic_bloom.cc | 47 +++++++------------------------------------ util/dynamic_bloom.h | 33 +++++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 45 deletions(-) diff --git a/util/dynamic_bloom.cc b/util/dynamic_bloom.cc index 84f964d9e..94df660ef 100644 --- a/util/dynamic_bloom.cc +++ b/util/dynamic_bloom.cc @@ -20,50 +20,17 @@ DynamicBloom::DynamicBloom(uint32_t total_bits, uint32_t (*hash_func)(const Slice& key), uint32_t num_probes) : hash_func_(hash_func), - total_bits_((total_bits + 7) / 8 * 8), - num_probes_(num_probes) { + kTotalBits((total_bits + 7) / 8 * 8), + kNumProbes(num_probes) { assert(hash_func_); - assert(num_probes_ > 0); - assert(total_bits_ > 0); - data_.reset(new unsigned char[total_bits_ / 8]()); + assert(kNumProbes > 0); + assert(kTotalBits > 0); + data_.reset(new unsigned char[kTotalBits / 8]()); } DynamicBloom::DynamicBloom(uint32_t total_bits, uint32_t num_probes) - : hash_func_(&BloomHash), - total_bits_((total_bits + 7) / 8 * 8), - num_probes_(num_probes) { - assert(num_probes_ > 0); - assert(total_bits_ > 0); - data_.reset(new unsigned char[total_bits_ / 8]()); + : DynamicBloom(total_bits, &BloomHash, num_probes) { } -void DynamicBloom::Add(const Slice& key) { - AddHash(hash_func_(key)); -} - -void DynamicBloom::AddHash(uint32_t h) { - const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits - for (uint32_t i = 0; i < num_probes_; i++) { - const uint32_t bitpos = h % total_bits_; - data_[bitpos/8] |= (1 << (bitpos % 8)); - h += delta; - } -} - -bool DynamicBloom::MayContain(const Slice& key) { - return (MayContainHash(hash_func_(key))); -} - -bool DynamicBloom::MayContainHash(uint32_t h) { - const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits - for (uint32_t i = 0; i < num_probes_; i++) { - const uint32_t bitpos = h % total_bits_; - if ((data_[bitpos/8] & (1 << (bitpos % 8))) - == 0) return false; - h += delta; - } - return true; -} - -} +} // rocksdb diff --git a/util/dynamic_bloom.h b/util/dynamic_bloom.h index aa29a4ae7..2b699dc77 100644 --- a/util/dynamic_bloom.h +++ b/util/dynamic_bloom.h @@ -13,9 +13,7 @@ namespace rocksdb { class Slice; class DynamicBloom { - public: - // total_bits: fixed total bits for the bloom // hash_func: customized hash function // num_probes: number of hash probes for a single key @@ -26,7 +24,7 @@ class DynamicBloom { explicit DynamicBloom(uint32_t total_bits, uint32_t num_probes = 6); // Assuming single threaded access to Add - void Add(const Slice& key); + void Add(const Slice& key) { AddHash(hash_func_(key)); } // Assuming single threaded access to Add void AddHash(uint32_t hash); @@ -39,9 +37,34 @@ class DynamicBloom { private: uint32_t (*hash_func_)(const Slice& key); - uint32_t total_bits_; - uint32_t num_probes_; + const uint32_t kTotalBits; + const uint32_t kNumProbes; std::unique_ptr data_; }; +inline bool DynamicBloom::MayContain(const Slice& key) { + return (MayContainHash(hash_func_(key))); +} + +inline bool DynamicBloom::MayContainHash(uint32_t h) { + const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits + for (uint32_t i = 0; i < kNumProbes; i++) { + const uint32_t bitpos = h % kTotalBits; + if (((data_[bitpos / 8]) & (1 << (bitpos % 8))) == 0) { + return false; + } + h += delta; + } + return true; } + +inline void DynamicBloom::AddHash(uint32_t h) { + const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits + for (uint32_t i = 0; i < kNumProbes; i++) { + const uint32_t bitpos = h % kTotalBits; + data_[bitpos / 8] |= (1 << (bitpos % 8)); + h += delta; + } +} + +} // rocksdb