提交 0ab0242f 编写于 作者: S sdong

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
上级 e93f044d
...@@ -16,6 +16,8 @@ ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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()),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册