prefetch bloom filter data block for L0 files

Summary: as title

Test Plan:
db_bench
the initial result is very promising. I will post results of complete
runs

Reviewers: dhruba, haobo, sdong, igor

Reviewed By: sdong

Subscribers: leveldb

Differential Revision: https://reviews.facebook.net/D18867
main
Lei Jin 11 years ago
parent 578cf84ddf
commit c83b085770
  1. 11
      db/version_set.cc
  2. 1
      db/version_set.h
  3. 2
      port/port_posix.h
  4. 7
      table/plain_table_reader.cc
  5. 2
      table/plain_table_reader.h
  6. 3
      table/table_reader.h
  7. 15
      util/dynamic_bloom.h

@ -567,6 +567,16 @@ void Version::Get(const ReadOptions& options,
continue; continue;
} }
// Prefetch table data to avoid cache miss if possible
if (level == 0) {
for (int i = 0; i < num_files; ++i) {
auto* r = files_[0][i]->table_reader;
if (r) {
r->Prepare(ikey);
}
}
}
// Get the list of files to search in this level // Get the list of files to search in this level
FileMetaData* const* files = &files_[level][0]; FileMetaData* const* files = &files_[level][0];
@ -607,6 +617,7 @@ void Version::Get(const ReadOptions& options,
for (int32_t i = start_index; i < num_files;) { for (int32_t i = start_index; i < num_files;) {
FileMetaData* f = files[i]; FileMetaData* f = files[i];
// Check if key is within a file's range. If search left bound and right // Check if key is within a file's range. If search left bound and right
// bound point to the same find, we are sure key falls in range. // bound point to the same find, we are sure key falls in range.
assert(level == 0 || i == start_index || assert(level == 0 || i == start_index ||

@ -92,6 +92,7 @@ class Version {
FileMetaData* seek_file; FileMetaData* seek_file;
int seek_file_level; int seek_file_level;
}; };
void Get(const ReadOptions&, const LookupKey& key, std::string* val, void Get(const ReadOptions&, const LookupKey& key, std::string* val,
Status* status, MergeContext* merge_context, GetStats* stats, Status* status, MergeContext* merge_context, GetStats* stats,
bool* value_found = nullptr); bool* value_found = nullptr);

@ -482,6 +482,8 @@ inline bool LZ4HC_Compress(const CompressionOptions &opts, const char* input,
#define CACHE_LINE_SIZE 64U #define CACHE_LINE_SIZE 64U
#define PREFETCH(addr, rw, locality) __builtin_prefetch(addr, rw, locality)
} // namespace port } // namespace port
} // namespace rocksdb } // namespace rocksdb

@ -610,6 +610,13 @@ Status PlainTableReader::Next(uint32_t* offset, ParsedInternalKey* key,
return Status::OK(); return Status::OK();
} }
void PlainTableReader::Prepare(const Slice& target) {
if (enable_bloom_) {
uint32_t prefix_hash = GetSliceHash(GetPrefix(target));
bloom_.Prefetch(prefix_hash);
}
}
Status PlainTableReader::Get(const ReadOptions& ro, const Slice& target, Status PlainTableReader::Get(const ReadOptions& ro, const Slice& target,
void* arg, void* arg,
bool (*saver)(void*, const ParsedInternalKey&, bool (*saver)(void*, const ParsedInternalKey&,

@ -57,6 +57,8 @@ class PlainTableReader: public TableReader {
Iterator* NewIterator(const ReadOptions&, Arena* arena = nullptr) override; Iterator* NewIterator(const ReadOptions&, Arena* arena = nullptr) override;
void Prepare(const Slice& target);
Status Get(const ReadOptions&, const Slice& key, void* arg, Status Get(const ReadOptions&, const Slice& key, void* arg,
bool (*result_handler)(void* arg, const ParsedInternalKey& k, bool (*result_handler)(void* arg, const ParsedInternalKey& k,
const Slice& v, bool), const Slice& v, bool),

@ -49,6 +49,9 @@ class TableReader {
virtual std::shared_ptr<const TableProperties> GetTableProperties() const = 0; virtual std::shared_ptr<const TableProperties> GetTableProperties() const = 0;
// Prepare work that can be done before the real Get()
virtual void Prepare(const Slice& target) {}
// Calls (*result_handler)(handle_context, ...) repeatedly, starting with // Calls (*result_handler)(handle_context, ...) repeatedly, starting with
// the entry found after a call to Seek(key), until result_handler returns // the entry found after a call to Seek(key), until result_handler returns
// false, where k is the actual internal key for a row found and v as the // false, where k is the actual internal key for a row found and v as the

@ -5,12 +5,12 @@
#pragma once #pragma once
#include <util/arena.h>
#include <port/port_posix.h>
#include <atomic> #include <atomic>
#include <memory> #include <memory>
#include "port/port.h"
#include <util/arena.h>
namespace rocksdb { namespace rocksdb {
class Slice; class Slice;
@ -53,6 +53,8 @@ class DynamicBloom {
// Multithreaded access to this function is OK // Multithreaded access to this function is OK
bool MayContainHash(uint32_t hash) const; bool MayContainHash(uint32_t hash) const;
void Prefetch(uint32_t h);
private: private:
uint32_t kTotalBits; uint32_t kTotalBits;
uint32_t kNumBlocks; uint32_t kNumBlocks;
@ -71,6 +73,13 @@ inline bool DynamicBloom::MayContain(const Slice& key) const {
return (MayContainHash(hash_func_(key))); return (MayContainHash(hash_func_(key)));
} }
inline void DynamicBloom::Prefetch(uint32_t h) {
if (kNumBlocks != 0) {
uint32_t b = ((h >> 11 | (h << 21)) % kNumBlocks) * (CACHE_LINE_SIZE * 8);
PREFETCH(&(data_[b]), 0, 3);
}
}
inline bool DynamicBloom::MayContainHash(uint32_t h) const { inline bool DynamicBloom::MayContainHash(uint32_t h) const {
assert(kNumBlocks > 0 || kTotalBits > 0); assert(kNumBlocks > 0 || kTotalBits > 0);
const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits

Loading…
Cancel
Save