diff --git a/db/c.cc b/db/c.cc index 8bdde3834..40dbe6ce3 100644 --- a/db/c.cc +++ b/db/c.cc @@ -426,6 +426,10 @@ void leveldb_options_set_max_file_size(leveldb_options_t* opt, size_t s) { opt->rep.max_file_size = s; } +void leveldb_options_set_disable_seek_autocompaction(leveldb_options_t* opt, uint8_t v) { + opt->rep.disable_seek_autocompaction = v; +} + void leveldb_options_set_compression(leveldb_options_t* opt, int t) { opt->rep.compression = static_cast(t); } diff --git a/db/version_set.cc b/db/version_set.cc index 4e37bf90e..6f8b5b5e2 100644 --- a/db/version_set.cc +++ b/db/version_set.cc @@ -402,11 +402,13 @@ Status Version::Get(const ReadOptions& options, const LookupKey& k, bool Version::UpdateStats(const GetStats& stats) { FileMetaData* f = stats.seek_file; if (f != nullptr) { - f->allowed_seeks--; - if (f->allowed_seeks <= 0 && file_to_compact_ == nullptr) { - file_to_compact_ = f; - file_to_compact_level_ = stats.seek_file_level; - return true; + if (!vset_->options_->disable_seek_autocompaction) { + f->allowed_seeks--; + if (f->allowed_seeks <= 0 && file_to_compact_ == nullptr) { + file_to_compact_ = f; + file_to_compact_level_ = stats.seek_file_level; + return true; + } } } return false; @@ -647,21 +649,23 @@ class VersionSet::Builder { FileMetaData* f = new FileMetaData(edit->new_files_[i].second); f->refs = 1; - // We arrange to automatically compact this file after - // a certain number of seeks. Let's assume: - // (1) One seek costs 10ms - // (2) Writing or reading 1MB costs 10ms (100MB/s) - // (3) A compaction of 1MB does 25MB of IO: - // 1MB read from this level - // 10-12MB read from next level (boundaries may be misaligned) - // 10-12MB written to next level - // This implies that 25 seeks cost the same as the compaction - // of 1MB of data. I.e., one seek costs approximately the - // same as the compaction of 40KB of data. We are a little - // conservative and allow approximately one seek for every 16KB - // of data before triggering a compaction. - f->allowed_seeks = static_cast((f->file_size / 16384U)); - if (f->allowed_seeks < 100) f->allowed_seeks = 100; + if (!vset_->options_->disable_seek_autocompaction) { + // We arrange to automatically compact this file after + // a certain number of seeks. Let's assume: + // (1) One seek costs 10ms + // (2) Writing or reading 1MB costs 10ms (100MB/s) + // (3) A compaction of 1MB does 25MB of IO: + // 1MB read from this level + // 10-12MB read from next level (boundaries may be misaligned) + // 10-12MB written to next level + // This implies that 25 seeks cost the same as the compaction + // of 1MB of data. I.e., one seek costs approximately the + // same as the compaction of 40KB of data. We are a little + // conservative and allow approximately one seek for every 16KB + // of data before triggering a compaction. + f->allowed_seeks = static_cast((f->file_size / 16384U)); + if (f->allowed_seeks < 100) f->allowed_seeks = 100; + } levels_[level].deleted_files.erase(f->number); levels_[level].added_files->insert(f); diff --git a/include/leveldb/c.h b/include/leveldb/c.h index 62e1f6439..c0788c164 100644 --- a/include/leveldb/c.h +++ b/include/leveldb/c.h @@ -189,6 +189,8 @@ LEVELDB_EXPORT void leveldb_options_set_block_restart_interval( leveldb_options_t*, int); LEVELDB_EXPORT void leveldb_options_set_max_file_size(leveldb_options_t*, size_t); +LEVELDB_EXPORT void leveldb_options_set_disable_seek_autocompaction(leveldb_options_t*, + uint8_t); enum { leveldb_no_compression = 0, leveldb_snappy_compression = 1 }; LEVELDB_EXPORT void leveldb_options_set_compression(leveldb_options_t*, int); diff --git a/include/leveldb/options.h b/include/leveldb/options.h index d755f46e7..305466306 100644 --- a/include/leveldb/options.h +++ b/include/leveldb/options.h @@ -145,6 +145,12 @@ struct LEVELDB_EXPORT Options { // Many applications will benefit from passing the result of // NewBloomFilterPolicy() here. const FilterPolicy* filter_policy = nullptr; + + // Storage systems with low seek times (SSDs) may want to + // disable seek count triggered autocompaction altogether. + // + // Default: false + bool disable_seek_autocompaction = false; }; // Options that control read operations