diff --git a/db/perf_context_test.cc b/db/perf_context_test.cc index 95b188022..9f98a33ef 100644 --- a/db/perf_context_test.cc +++ b/db/perf_context_test.cc @@ -1,3 +1,4 @@ +#include #include #include @@ -7,17 +8,25 @@ #include "util/stop_watch.h" #include "util/testharness.h" - -namespace leveldb { +bool FLAGS_random_key = false; +int FLAGS_total_keys = 100; +int FLAGS_write_buffer_size = 1000000000; +int FLAGS_max_write_buffer_number = 8; +int FLAGS_min_write_buffer_number_to_merge = 7; // Path to the database on file system -const std::string kDbName = test::TmpDir() + "/perf_context_test"; +const std::string kDbName = leveldb::test::TmpDir() + "/perf_context_test"; -std::shared_ptr OpenDb(size_t write_buffer_size) { +namespace leveldb { + +std::shared_ptr OpenDb() { DB* db; Options options; options.create_if_missing = true; - options.write_buffer_size = write_buffer_size; + options.write_buffer_size = FLAGS_write_buffer_size; + options.max_write_buffer_number = FLAGS_max_write_buffer_number; + options.min_write_buffer_number_to_merge = + FLAGS_min_write_buffer_number_to_merge; Status s = DB::Open(options, kDbName, &db); ASSERT_OK(s); return std::shared_ptr(db); @@ -25,8 +34,6 @@ std::shared_ptr OpenDb(size_t write_buffer_size) { class PerfContextTest { }; -int kTotalKeys = 100; - TEST(PerfContextTest, StopWatchNanoOverhead) { // profile the timer cost by itself! const int kTotalIterations = 1000000; @@ -68,7 +75,7 @@ TEST(PerfContextTest, StopWatchOverhead) { void ProfileKeyComparison() { DestroyDB(kDbName, Options()); // Start this test with a fresh DB - auto db = OpenDb(1000000000); + auto db = OpenDb(); WriteOptions write_options; ReadOptions read_options; @@ -77,9 +84,9 @@ void ProfileKeyComparison() { uint64_t total_user_key_comparison_put = 0; uint64_t max_user_key_comparison_get = 0; - std::cout << "Inserting " << kTotalKeys << " key/value pairs\n...\n"; + std::cout << "Inserting " << FLAGS_total_keys << " key/value pairs\n...\n"; - for (int i = 0; i < kTotalKeys; ++i) { + for (int i = 0; i < FLAGS_total_keys; ++i) { std::string key = "k" + std::to_string(i); std::string value = "v" + std::to_string(i); @@ -102,28 +109,97 @@ void ProfileKeyComparison() { << "max user key comparison get: " << max_user_key_comparison_get << "\n" << "avg user key comparison get:" - << total_user_key_comparison_get/kTotalKeys << "\n"; + << total_user_key_comparison_get/FLAGS_total_keys << "\n"; + } TEST(PerfContextTest, KeyComparisonCount) { - SetPerfLevel(kDisable); + SetPerfLevel(kEnableCount); ProfileKeyComparison(); - SetPerfLevel(kEnableCount); + SetPerfLevel(kDisable); ProfileKeyComparison(); SetPerfLevel(kEnableTime); ProfileKeyComparison(); } +// make perf_context_test +// export LEVELDB_TESTS=PerfContextTest.SeekKeyComparison +// For one memtable: +// ./perf_context_test --write_buffer_size=500000 --total_keys=10000 +// For two memtables: +// ./perf_context_test --write_buffer_size=250000 --total_keys=10000 +// Specify --random_key=1 to shuffle the key before insertion +// Results show that, for sequential insertion, worst-case Seek Key comparison +// is close to the total number of keys (linear), when there is only one +// memtable. When there are two memtables, even the avg Seek Key comparison +// starts to become linear to the input size. + +TEST(PerfContextTest, SeekKeyComparison) { + DestroyDB(kDbName, Options()); + auto db = OpenDb(); + WriteOptions write_options; + ReadOptions read_options; + + std::cout << "Inserting " << FLAGS_total_keys << " key/value pairs\n...\n"; + + std::vector keys; + for (int i = 0; i < FLAGS_total_keys; ++i) { + keys.push_back(i); + } + + if (FLAGS_random_key) { + std::random_shuffle(keys.begin(), keys.end()); + } + + for (const int i : keys) { + std::string key = "k" + std::to_string(i); + std::string value = "v" + std::to_string(i); + + db->Put(write_options, key, value); + } + + HistogramImpl histogram; + for (int i = 0; i < FLAGS_total_keys; ++i) { + std::string key = "k" + std::to_string(i); + std::string value = "v" + std::to_string(i); + + std::unique_ptr iter(db->NewIterator(read_options)); + perf_context.Reset(); + iter->Seek(key); + ASSERT_TRUE(iter->Valid()); + ASSERT_EQ(iter->value().ToString(), value); + histogram.Add(perf_context.user_key_comparison_count); + } + std::cout << histogram.ToString(); +} + } int main(int argc, char** argv) { - if (argc > 1) { - leveldb::kTotalKeys = std::stoi(argv[1]); + for (int i = 1; i < argc; i++) { + int n; + char junk; + + if (sscanf(argv[i], "--write_buffer_size=%d%c", &n, &junk) == 1) { + FLAGS_write_buffer_size = n; + } + + if (sscanf(argv[i], "--total_keys=%d%c", &n, &junk) == 1) { + FLAGS_total_keys = n; + } + + if (sscanf(argv[i], "--random_key=%d%c", &n, &junk) == 1 && + (n == 0 || n == 1)) { + FLAGS_random_key = n; + } + } + std::cout << kDbName << "\n"; + leveldb::test::RunAllTests(); return 0; }