From 4b86fe11233ec5d26ef5caf2b713fdec49c786ed Mon Sep 17 00:00:00 2001 From: Peter Dillinger Date: Fri, 17 Jan 2020 19:36:09 -0800 Subject: [PATCH] Log warning for high bits/key in legacy Bloom filter (#6312) Summary: Help users that would benefit most from new Bloom filter implementation by logging a warning that recommends the using format_version >= 5. Pull Request resolved: https://github.com/facebook/rocksdb/pull/6312 Test Plan: $ (for BPK in 10 13 14 19 20 50; do ./filter_bench -quick -impl=0 -bits_per_key=$BPK -m_queries=1 2>&1; done) | grep 'its/key' Bits/key actual: 10.0647 Bits/key actual: 13.0593 [WARN] [/block_based/filter_policy.cc:546] Using legacy Bloom filter with high (14) bits/key. Significant filter space and/or accuracy improvement is available with format_verion>=5. Bits/key actual: 14.0581 [WARN] [/block_based/filter_policy.cc:546] Using legacy Bloom filter with high (19) bits/key. Significant filter space and/or accuracy improvement is available with format_verion>=5. Bits/key actual: 19.0542 [WARN] [/block_based/filter_policy.cc:546] Using legacy Bloom filter with high (20) bits/key. Dramatic filter space and/or accuracy improvement is available with format_verion>=5. Bits/key actual: 20.0584 [WARN] [/block_based/filter_policy.cc:546] Using legacy Bloom filter with high (50) bits/key. Dramatic filter space and/or accuracy improvement is available with format_verion>=5. Bits/key actual: 50.0577 Differential Revision: D19457191 Pulled By: pdillinger fbshipit-source-id: 073d94cde5c70e03a160f953e1100c15ea83eda4 --- docs/static/images/bloom_fp_vs_bpk.png | Bin 0 -> 51924 bytes include/rocksdb/filter_policy.h | 3 +++ .../block_based/block_based_table_builder.cc | 1 + table/block_based/filter_policy.cc | 20 +++++++++++++++++- table/block_based/filter_policy_internal.h | 5 +++++ table/block_based/mock_block_based_table.h | 1 + util/filter_bench.cc | 4 ++++ 7 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 docs/static/images/bloom_fp_vs_bpk.png diff --git a/docs/static/images/bloom_fp_vs_bpk.png b/docs/static/images/bloom_fp_vs_bpk.png new file mode 100644 index 0000000000000000000000000000000000000000..e83f4d085078d214ea995947d39a36ed38155090 GIT binary patch literal 51924 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
  • gqx%2EhWZ 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 Tk|xw{fq(MSDpDULOauQH#=}QX literal 0 HcmV?d00001 diff --git a/include/rocksdb/filter_policy.h b/include/rocksdb/filter_policy.h index ad6862d5f..fa918c80d 100644 --- a/include/rocksdb/filter_policy.h +++ b/include/rocksdb/filter_policy.h @@ -101,6 +101,9 @@ struct FilterBuildingContext { // The table level at time of constructing the SST file, or -1 if unknown. // (The table file could later be used at a different level.) int level_at_creation = -1; + + // An optional logger for reporting errors, warnings, etc. + Logger* info_log = nullptr; }; // We add a new format of filter block called full filter block diff --git a/table/block_based/block_based_table_builder.cc b/table/block_based/block_based_table_builder.cc index d4e0de5a8..8a756577f 100644 --- a/table/block_based/block_based_table_builder.cc +++ b/table/block_based/block_based_table_builder.cc @@ -425,6 +425,7 @@ struct BlockBasedTableBuilder::Rep { context.column_family_name = column_family_name; context.compaction_style = ioptions.compaction_style; context.level_at_creation = level_at_creation; + context.info_log = ioptions.info_log; filter_builder.reset(CreateFilterBlockBuilder( ioptions, moptions, context, use_delta_encoding_for_index_values, p_index_builder_)); diff --git a/table/block_based/filter_policy.cc b/table/block_based/filter_policy.cc index eb2551f2f..1b49d554d 100644 --- a/table/block_based/filter_policy.cc +++ b/table/block_based/filter_policy.cc @@ -419,7 +419,7 @@ const std::vector BloomFilterPolicy::kAllUserModes = { }; BloomFilterPolicy::BloomFilterPolicy(double bits_per_key, Mode mode) - : mode_(mode) { + : mode_(mode), warned_(false) { // Sanitize bits_per_key if (bits_per_key < 1.0) { bits_per_key = 1.0; @@ -527,6 +527,24 @@ FilterBitsBuilder* BloomFilterPolicy::GetBuilderWithContext( case kFastLocalBloom: return new FastLocalBloomBitsBuilder(millibits_per_key_); case kLegacyBloom: + if (whole_bits_per_key_ >= 14 && context.info_log && + !warned_.load(std::memory_order_relaxed)) { + warned_ = true; + const char* adjective; + if (whole_bits_per_key_ >= 20) { + adjective = "Dramatic"; + } else { + adjective = "Significant"; + } + // For more details, see + // https://github.com/facebook/rocksdb/wiki/RocksDB-Bloom-Filter + ROCKS_LOG_WARN( + context.info_log, + "Using legacy Bloom filter with high (%d) bits/key. " + "%s filter space and/or accuracy improvement is available " + "with format_version>=5.", + whole_bits_per_key_, adjective); + } return new LegacyBloomBitsBuilder(whole_bits_per_key_); } } diff --git a/table/block_based/filter_policy_internal.h b/table/block_based/filter_policy_internal.h index b92980a54..6fe344c48 100644 --- a/table/block_based/filter_policy_internal.h +++ b/table/block_based/filter_policy_internal.h @@ -8,6 +8,7 @@ #pragma once +#include #include #include #include @@ -125,6 +126,10 @@ class BloomFilterPolicy : public FilterPolicy { // implementation) for building new SST filters. Mode mode_; + // Whether relevant warnings have been logged already. (Remember so we + // only report once per BloomFilterPolicy instance, to keep the noise down.) + mutable std::atomic warned_; + // For newer Bloom filter implementation(s) FilterBitsReader* GetBloomBitsReader(const Slice& contents) const; }; diff --git a/table/block_based/mock_block_based_table.h b/table/block_based/mock_block_based_table.h index 52891b1bd..b38de08df 100644 --- a/table/block_based/mock_block_based_table.h +++ b/table/block_based/mock_block_based_table.h @@ -47,6 +47,7 @@ class MockBlockBasedTableTester { context.column_family_name = "mock_cf"; context.compaction_style = ioptions_.compaction_style; context.level_at_creation = kMockLevel; + context.info_log = ioptions_.info_log; return BloomFilterPolicy::GetBuilderFromContext(context); } }; diff --git a/util/filter_bench.cc b/util/filter_bench.cc index 45e042a15..04b419dd3 100644 --- a/util/filter_bench.cc +++ b/util/filter_bench.cc @@ -26,6 +26,7 @@ int main() { #include "util/gflags_compat.h" #include "util/hash.h" #include "util/random.h" +#include "util/stderr_logger.h" #include "util/stop_watch.h" using GFLAGS_NAMESPACE::ParseCommandLineFlags; @@ -112,6 +113,7 @@ using rocksdb::ParsedFullFilterBlock; using rocksdb::PlainTableBloomV1; using rocksdb::Random32; using rocksdb::Slice; +using rocksdb::StderrLogger; using rocksdb::mock::MockBlockBasedTableTester; struct KeyMaker { @@ -243,6 +245,7 @@ struct FilterBench : public MockBlockBasedTableTester { Random32 random_; std::ostringstream fp_rate_report_; Arena arena_; + StderrLogger stderr_logger_; FilterBench() : MockBlockBasedTableTester(new BloomFilterPolicy( @@ -252,6 +255,7 @@ struct FilterBench : public MockBlockBasedTableTester { for (uint32_t i = 0; i < FLAGS_batch_size; ++i) { kms_.emplace_back(FLAGS_key_size < 8 ? 8 : FLAGS_key_size); } + ioptions_.info_log = &stderr_logger_; } void Go(); -- GitLab