[RocksDB Performance Branch] Avoid sorting in Version::Get() by presorting them in VersionSet::Builder::SaveTo()
Summary: Pre-sort files in VersionSet::Builder::SaveTo() so that when getting the value, no need to sort them. It can avoid the costs of vector operations and sorting in Version::Get(). Test Plan: make all check Reviewers: haobo, kailiu, dhruba Reviewed By: dhruba CC: nkg-, igor, leveldb Differential Revision: https://reviews.facebook.net/D14409
This commit is contained in:
parent
0304e3d2ff
commit
bc5dd19b14
@ -450,17 +450,12 @@ void Version::Get(const ReadOptions& options,
|
|||||||
// levels. Therefore we are guaranteed that if we find data
|
// levels. Therefore we are guaranteed that if we find data
|
||||||
// in an smaller level, later levels are irrelevant (unless we
|
// in an smaller level, later levels are irrelevant (unless we
|
||||||
// are MergeInProgress).
|
// are MergeInProgress).
|
||||||
std::vector<FileMetaData*> important_files;
|
|
||||||
for (int level = 0; level < vset_->NumberLevels(); level++) {
|
for (int level = 0; level < vset_->NumberLevels(); level++) {
|
||||||
size_t num_files = files_[level].size();
|
size_t num_files = files_[level].size();
|
||||||
if (num_files == 0) continue;
|
if (num_files == 0) continue;
|
||||||
|
|
||||||
// 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];
|
||||||
important_files.clear();
|
|
||||||
if (level == 0) {
|
|
||||||
important_files.reserve(num_files);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Some files may overlap each other. We find
|
// Some files may overlap each other. We find
|
||||||
// all files that overlap user_key and process them in order from
|
// all files that overlap user_key and process them in order from
|
||||||
@ -478,44 +473,42 @@ void Version::Get(const ReadOptions& options,
|
|||||||
start_index = FindFile(vset_->icmp_, files_[level], ikey);
|
start_index = FindFile(vset_->icmp_, files_[level], ikey);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Traverse the list, finding all overlapping files.
|
|
||||||
for (uint32_t i = start_index; i < num_files; i++) {
|
|
||||||
FileMetaData* f = files[i];
|
|
||||||
if (ucmp->Compare(user_key, f->smallest.user_key()) >= 0 &&
|
|
||||||
ucmp->Compare(user_key, f->largest.user_key()) <= 0) {
|
|
||||||
important_files.push_back(f);
|
|
||||||
} else if (level > 0) {
|
|
||||||
// If on Level-n (n>=1) then the files are sorted.
|
|
||||||
// So we can stop looking when we are past the ikey.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (important_files.empty()) continue;
|
|
||||||
|
|
||||||
if (level == 0) {
|
|
||||||
if (vset_->options_->compaction_style == kCompactionStyleUniversal) {
|
|
||||||
std::sort(important_files.begin(), important_files.end(), NewestFirstBySeqNo);
|
|
||||||
} else {
|
|
||||||
std::sort(important_files.begin(), important_files.end(), NewestFirst);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Sanity check to make sure that the files are correctly sorted
|
|
||||||
#ifndef NDEBUG
|
|
||||||
num_files = important_files.size();
|
|
||||||
for (uint32_t i = 1; i < num_files; ++i) {
|
|
||||||
FileMetaData* a = important_files[i-1];
|
|
||||||
FileMetaData* b = important_files[i];
|
|
||||||
int comp_sign = vset_->icmp_.Compare(a->largest, b->smallest);
|
|
||||||
assert(comp_sign < 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Traverse each relevant file to find the desired key
|
// Traverse each relevant file to find the desired key
|
||||||
num_files = important_files.size();
|
#ifndef NDEBUG
|
||||||
for (uint32_t i = 0; i < num_files; ++i) {
|
FileMetaData* prev_file = nullptr;
|
||||||
FileMetaData* f = important_files[i];
|
#endif
|
||||||
|
for (uint32_t i = start_index; i < num_files; ++i) {
|
||||||
|
FileMetaData* f = files[i];
|
||||||
|
if (ucmp->Compare(user_key, f->smallest.user_key()) < 0 ||
|
||||||
|
ucmp->Compare(user_key, f->largest.user_key()) > 0) {
|
||||||
|
// Only process overlapping files.
|
||||||
|
if (level > 0) {
|
||||||
|
// If on Level-n (n>=1) then the files are sorted.
|
||||||
|
// So we can stop looking when we are past the ikey.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// TODO: do we want to check file ranges for level0 files at all?
|
||||||
|
// For new SST format where Get() is fast, we might want to consider
|
||||||
|
// to avoid those two comparisons, if it can filter out too few files.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// Sanity check to make sure that the files are correctly sorted
|
||||||
|
if (prev_file) {
|
||||||
|
if (level != 0) {
|
||||||
|
int comp_sign = vset_->icmp_.Compare(prev_file->largest, f->smallest);
|
||||||
|
assert(comp_sign < 0);
|
||||||
|
} else {
|
||||||
|
// level == 0, the current file cannot be newer than the previous one.
|
||||||
|
if (vset_->options_->compaction_style == kCompactionStyleUniversal) {
|
||||||
|
assert(!NewestFirstBySeqNo(f, prev_file));
|
||||||
|
} else {
|
||||||
|
assert(!NewestFirst(f, prev_file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prev_file = f;
|
||||||
|
#endif
|
||||||
bool tableIO = false;
|
bool tableIO = false;
|
||||||
*status = vset_->table_cache_->Get(options, f->number, f->file_size,
|
*status = vset_->table_cache_->Get(options, f->number, f->file_size,
|
||||||
ikey, &saver, SaveValue, &tableIO,
|
ikey, &saver, SaveValue, &tableIO,
|
||||||
@ -1113,6 +1106,13 @@ class VersionSet::Builder {
|
|||||||
MaybeAddFile(v, level, *base_iter);
|
MaybeAddFile(v, level, *base_iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Pre-sort level0 for Get()
|
||||||
|
if (vset_->options_->compaction_style == kCompactionStyleUniversal) {
|
||||||
|
std::sort(v->files_[0].begin(), v->files_[0].end(), NewestFirstBySeqNo);
|
||||||
|
} else {
|
||||||
|
std::sort(v->files_[0].begin(), v->files_[0].end(), NewestFirst);
|
||||||
|
}
|
||||||
|
|
||||||
CheckConsistency(v);
|
CheckConsistency(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user