]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/rocksdb/microbench/ribbon_bench.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rocksdb / microbench / ribbon_bench.cc
diff --git a/ceph/src/rocksdb/microbench/ribbon_bench.cc b/ceph/src/rocksdb/microbench/ribbon_bench.cc
new file mode 100644 (file)
index 0000000..d0fb2ec
--- /dev/null
@@ -0,0 +1,155 @@
+//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under both the GPLv2 (found in the
+//  COPYING file in the root directory) and Apache 2.0 License
+//  (found in the LICENSE.Apache file in the root directory).
+
+// this is a simple micro-benchmark for compare ribbon filter vs. other filter
+// for more comprehensive, please check the dedicate util/filter_bench.
+#include "benchmark/benchmark.h"
+#include "table/block_based/filter_policy_internal.h"
+#include "table/block_based/mock_block_based_table.h"
+
+namespace ROCKSDB_NAMESPACE {
+
+struct KeyMaker {
+  explicit KeyMaker(size_t avg_size)
+      : smallest_size_(avg_size),
+        buf_size_(avg_size + 11),  // pad to vary key size and alignment
+        buf_(new char[buf_size_]) {
+    memset(buf_.get(), 0, buf_size_);
+    assert(smallest_size_ > 8);
+  }
+  size_t smallest_size_;
+  size_t buf_size_;
+  std::unique_ptr<char[]> buf_;
+
+  // Returns a unique(-ish) key based on the given parameter values. Each
+  // call returns a Slice from the same buffer so previously returned
+  // Slices should be considered invalidated.
+  Slice Get(uint32_t filter_num, uint32_t val_num) const {
+    size_t start = val_num % 4;
+    size_t len = smallest_size_;
+    // To get range [avg_size - 2, avg_size + 2]
+    // use range [smallest_size, smallest_size + 4]
+    len += FastRange32((val_num >> 5) * 1234567891, 5);
+    char *data = buf_.get() + start;
+    // Populate key data such that all data makes it into a key of at
+    // least 8 bytes. We also don't want all the within-filter key
+    // variance confined to a contiguous 32 bits, because then a 32 bit
+    // hash function can "cheat" the false positive rate by
+    // approximating a perfect hash.
+    EncodeFixed32(data, val_num);
+    EncodeFixed32(data + 4, filter_num + val_num);
+    // ensure clearing leftovers from different alignment
+    EncodeFixed32(data + 8, 0);
+    return {data, len};
+  }
+};
+
+// benchmark arguments:
+// 0. filter impl (like filter_bench -impl)
+// 1. filter config bits_per_key
+// 2. average data key length
+// 3. data entry number
+static void CustomArguments(benchmark::internal::Benchmark *b) {
+  const auto kImplCount =
+      static_cast<int>(BloomLikeFilterPolicy::GetAllFixedImpls().size());
+  for (int filter_impl = 0; filter_impl < kImplCount; ++filter_impl) {
+    for (int bits_per_key : {10, 20}) {
+      for (int key_len_avg : {10, 100}) {
+        for (int64_t entry_num : {1 << 10, 1 << 20}) {
+          b->Args({filter_impl, bits_per_key, key_len_avg, entry_num});
+        }
+      }
+    }
+  }
+  b->ArgNames({"filter_impl", "bits_per_key", "key_len_avg", "entry_num"});
+}
+
+static void FilterBuild(benchmark::State &state) {
+  // setup data
+  auto filter = BloomLikeFilterPolicy::Create(
+      BloomLikeFilterPolicy::GetAllFixedImpls().at(state.range(0)),
+      static_cast<double>(state.range(1)));
+  auto tester = std::make_unique<mock::MockBlockBasedTableTester>(filter);
+  KeyMaker km(state.range(2));
+  std::unique_ptr<const char[]> owner;
+  const int64_t kEntryNum = state.range(3);
+  auto rnd = Random32(12345);
+  uint32_t filter_num = rnd.Next();
+  // run the test
+  for (auto _ : state) {
+    std::unique_ptr<FilterBitsBuilder> builder(tester->GetBuilder());
+    for (uint32_t i = 0; i < kEntryNum; i++) {
+      builder->AddKey(km.Get(filter_num, i));
+    }
+    auto ret = builder->Finish(&owner);
+    state.counters["size"] = static_cast<double>(ret.size());
+  }
+}
+BENCHMARK(FilterBuild)->Apply(CustomArguments);
+
+static void FilterQueryPositive(benchmark::State &state) {
+  // setup data
+  auto filter = BloomLikeFilterPolicy::Create(
+      BloomLikeFilterPolicy::GetAllFixedImpls().at(state.range(0)),
+      static_cast<double>(state.range(1)));
+  auto tester = std::make_unique<mock::MockBlockBasedTableTester>(filter);
+  KeyMaker km(state.range(2));
+  std::unique_ptr<const char[]> owner;
+  const int64_t kEntryNum = state.range(3);
+  auto rnd = Random32(12345);
+  uint32_t filter_num = rnd.Next();
+  std::unique_ptr<FilterBitsBuilder> builder(tester->GetBuilder());
+  for (uint32_t i = 0; i < kEntryNum; i++) {
+    builder->AddKey(km.Get(filter_num, i));
+  }
+  auto data = builder->Finish(&owner);
+  std::unique_ptr<FilterBitsReader> reader{filter->GetFilterBitsReader(data)};
+
+  // run test
+  uint32_t i = 0;
+  for (auto _ : state) {
+    i++;
+    i = i % kEntryNum;
+    reader->MayMatch(km.Get(filter_num, i));
+  }
+}
+BENCHMARK(FilterQueryPositive)->Apply(CustomArguments);
+
+static void FilterQueryNegative(benchmark::State &state) {
+  // setup data
+  auto filter = BloomLikeFilterPolicy::Create(
+      BloomLikeFilterPolicy::GetAllFixedImpls().at(state.range(0)),
+      static_cast<double>(state.range(1)));
+  auto tester = std::make_unique<mock::MockBlockBasedTableTester>(filter);
+  KeyMaker km(state.range(2));
+  std::unique_ptr<const char[]> owner;
+  const int64_t kEntryNum = state.range(3);
+  auto rnd = Random32(12345);
+  uint32_t filter_num = rnd.Next();
+  std::unique_ptr<FilterBitsBuilder> builder(tester->GetBuilder());
+  for (uint32_t i = 0; i < kEntryNum; i++) {
+    builder->AddKey(km.Get(filter_num, i));
+  }
+  auto data = builder->Finish(&owner);
+  std::unique_ptr<FilterBitsReader> reader{filter->GetFilterBitsReader(data)};
+
+  // run test
+  uint32_t i = 0;
+  double fp_cnt = 0;
+  for (auto _ : state) {
+    i++;
+    auto result = reader->MayMatch(km.Get(filter_num + 1, i));
+    if (result) {
+      fp_cnt++;
+    }
+  }
+  state.counters["fp_pct"] =
+      benchmark::Counter(fp_cnt * 100, benchmark::Counter::kAvgIterations);
+}
+BENCHMARK(FilterQueryNegative)->Apply(CustomArguments);
+
+}  // namespace ROCKSDB_NAMESPACE
+
+BENCHMARK_MAIN();