VersionBuilder to use unordered set and map to store added and deleted files
Summary: Set operations in VerisonBuilder is shown as a performance bottleneck of restarting DB when there are lots of files. Make both of added_files and deleted_files use unordered set or map. Only when adding the files, sort the added files. Test Plan: make all check Reviewers: yhchiang, rven, igor Reviewed By: igor Subscribers: hermanlee4, leveldb, dhruba, ljin Differential Revision: https://reviews.facebook.net/D30051
This commit is contained in:
parent
e93f044d99
commit
0ab0242f37
@ -16,6 +16,8 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "db/dbformat.h"
|
#include "db/dbformat.h"
|
||||||
@ -69,10 +71,10 @@ class VersionBuilder::Rep {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::set<FileMetaData*, FileComparator> FileSet;
|
|
||||||
struct LevelState {
|
struct LevelState {
|
||||||
std::set<uint64_t> deleted_files;
|
std::unordered_set<uint64_t> deleted_files;
|
||||||
FileSet* added_files;
|
// Map from file number to file meta data.
|
||||||
|
std::unordered_map<uint64_t, FileMetaData*> added_files;
|
||||||
};
|
};
|
||||||
|
|
||||||
const EnvOptions& env_options_;
|
const EnvOptions& env_options_;
|
||||||
@ -93,25 +95,13 @@ class VersionBuilder::Rep {
|
|||||||
level_nonzero_cmp_.sort_method = FileComparator::kLevelNon0;
|
level_nonzero_cmp_.sort_method = FileComparator::kLevelNon0;
|
||||||
level_nonzero_cmp_.internal_comparator =
|
level_nonzero_cmp_.internal_comparator =
|
||||||
base_vstorage_->InternalComparator();
|
base_vstorage_->InternalComparator();
|
||||||
|
|
||||||
levels_[0].added_files = new FileSet(level_zero_cmp_);
|
|
||||||
for (int level = 1; level < base_vstorage_->num_levels(); level++) {
|
|
||||||
levels_[level].added_files = new FileSet(level_nonzero_cmp_);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~Rep() {
|
~Rep() {
|
||||||
for (int level = 0; level < base_vstorage_->num_levels(); level++) {
|
for (int level = 0; level < base_vstorage_->num_levels(); level++) {
|
||||||
const FileSet* added = levels_[level].added_files;
|
const auto& added = levels_[level].added_files;
|
||||||
std::vector<FileMetaData*> to_unref;
|
for (auto& pair : added) {
|
||||||
to_unref.reserve(added->size());
|
FileMetaData* f = pair.second;
|
||||||
for (FileSet::const_iterator it = added->begin(); it != added->end();
|
|
||||||
++it) {
|
|
||||||
to_unref.push_back(*it);
|
|
||||||
}
|
|
||||||
delete added;
|
|
||||||
for (uint32_t i = 0; i < to_unref.size(); i++) {
|
|
||||||
FileMetaData* f = to_unref[i];
|
|
||||||
f->refs--;
|
f->refs--;
|
||||||
if (f->refs <= 0) {
|
if (f->refs <= 0) {
|
||||||
if (f->table_reader_handle) {
|
if (f->table_reader_handle) {
|
||||||
@ -175,27 +165,20 @@ class VersionBuilder::Rep {
|
|||||||
// is possibly moved from lower level to higher level in current
|
// is possibly moved from lower level to higher level in current
|
||||||
// version
|
// version
|
||||||
for (int l = level + 1; !found && l < base_vstorage_->num_levels(); l++) {
|
for (int l = level + 1; !found && l < base_vstorage_->num_levels(); l++) {
|
||||||
const FileSet* added = levels_[l].added_files;
|
auto& level_added = levels_[l].added_files;
|
||||||
for (FileSet::const_iterator added_iter = added->begin();
|
auto got = level_added.find(number);
|
||||||
added_iter != added->end(); ++added_iter) {
|
if (got != level_added.end()) {
|
||||||
FileMetaData* f = *added_iter;
|
found = true;
|
||||||
if (f->fd.GetNumber() == number) {
|
break;
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// maybe this file was added in a previous edit that was Applied
|
// maybe this file was added in a previous edit that was Applied
|
||||||
if (!found) {
|
if (!found) {
|
||||||
const FileSet* added = levels_[level].added_files;
|
auto& level_added = levels_[level].added_files;
|
||||||
for (FileSet::const_iterator added_iter = added->begin();
|
auto got = level_added.find(number);
|
||||||
added_iter != added->end(); ++added_iter) {
|
if (got != level_added.end()) {
|
||||||
FileMetaData* f = *added_iter;
|
found = true;
|
||||||
if (f->fd.GetNumber() == number) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
@ -224,8 +207,10 @@ class VersionBuilder::Rep {
|
|||||||
FileMetaData* f = new FileMetaData(new_file.second);
|
FileMetaData* f = new FileMetaData(new_file.second);
|
||||||
f->refs = 1;
|
f->refs = 1;
|
||||||
|
|
||||||
|
assert(levels_[level].added_files.find(f->fd.GetNumber()) ==
|
||||||
|
levels_[level].added_files.end());
|
||||||
levels_[level].deleted_files.erase(f->fd.GetNumber());
|
levels_[level].deleted_files.erase(f->fd.GetNumber());
|
||||||
levels_[level].added_files->insert(f);
|
levels_[level].added_files[f->fd.GetNumber()] = f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,8 +226,16 @@ class VersionBuilder::Rep {
|
|||||||
const auto& base_files = base_vstorage_->LevelFiles(level);
|
const auto& base_files = base_vstorage_->LevelFiles(level);
|
||||||
auto base_iter = base_files.begin();
|
auto base_iter = base_files.begin();
|
||||||
auto base_end = base_files.end();
|
auto base_end = base_files.end();
|
||||||
const auto& added_files = *levels_[level].added_files;
|
const auto& unordered_added_files = levels_[level].added_files;
|
||||||
vstorage->Reserve(level, base_files.size() + added_files.size());
|
vstorage->Reserve(level,
|
||||||
|
base_files.size() + unordered_added_files.size());
|
||||||
|
|
||||||
|
// Sort added files for the level.
|
||||||
|
autovector<FileMetaData*> added_files;
|
||||||
|
for (const auto& pair : unordered_added_files) {
|
||||||
|
added_files.push_back(pair.second);
|
||||||
|
}
|
||||||
|
std::sort(added_files.begin(), added_files.end(), cmp);
|
||||||
|
|
||||||
for (const auto& added : added_files) {
|
for (const auto& added : added_files) {
|
||||||
// Add all smaller files listed in base_
|
// Add all smaller files listed in base_
|
||||||
@ -266,7 +259,8 @@ class VersionBuilder::Rep {
|
|||||||
void LoadTableHandlers() {
|
void LoadTableHandlers() {
|
||||||
assert(table_cache_ != nullptr);
|
assert(table_cache_ != nullptr);
|
||||||
for (int level = 0; level < base_vstorage_->num_levels(); level++) {
|
for (int level = 0; level < base_vstorage_->num_levels(); level++) {
|
||||||
for (auto& file_meta : *(levels_[level].added_files)) {
|
for (auto& file_meta_pair : levels_[level].added_files) {
|
||||||
|
auto* file_meta = file_meta_pair.second;
|
||||||
assert(!file_meta->table_reader_handle);
|
assert(!file_meta->table_reader_handle);
|
||||||
table_cache_->FindTable(
|
table_cache_->FindTable(
|
||||||
env_options_, *(base_vstorage_->InternalComparator()),
|
env_options_, *(base_vstorage_->InternalComparator()),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user