|
|
@ -1,3 +1,4 @@ |
|
|
|
|
|
|
|
#include <algorithm> |
|
|
|
#include <iostream> |
|
|
|
#include <iostream> |
|
|
|
#include <vector> |
|
|
|
#include <vector> |
|
|
|
|
|
|
|
|
|
|
@ -7,17 +8,25 @@ |
|
|
|
#include "util/stop_watch.h" |
|
|
|
#include "util/stop_watch.h" |
|
|
|
#include "util/testharness.h" |
|
|
|
#include "util/testharness.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool FLAGS_random_key = false; |
|
|
|
namespace leveldb { |
|
|
|
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
|
|
|
|
// 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"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace leveldb { |
|
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<DB> OpenDb(size_t write_buffer_size) { |
|
|
|
std::shared_ptr<DB> OpenDb() { |
|
|
|
DB* db; |
|
|
|
DB* db; |
|
|
|
Options options; |
|
|
|
Options options; |
|
|
|
options.create_if_missing = true; |
|
|
|
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); |
|
|
|
Status s = DB::Open(options, kDbName, &db); |
|
|
|
ASSERT_OK(s); |
|
|
|
ASSERT_OK(s); |
|
|
|
return std::shared_ptr<DB>(db); |
|
|
|
return std::shared_ptr<DB>(db); |
|
|
@ -25,8 +34,6 @@ std::shared_ptr<DB> OpenDb(size_t write_buffer_size) { |
|
|
|
|
|
|
|
|
|
|
|
class PerfContextTest { }; |
|
|
|
class PerfContextTest { }; |
|
|
|
|
|
|
|
|
|
|
|
int kTotalKeys = 100; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TEST(PerfContextTest, StopWatchNanoOverhead) { |
|
|
|
TEST(PerfContextTest, StopWatchNanoOverhead) { |
|
|
|
// profile the timer cost by itself!
|
|
|
|
// profile the timer cost by itself!
|
|
|
|
const int kTotalIterations = 1000000; |
|
|
|
const int kTotalIterations = 1000000; |
|
|
@ -68,7 +75,7 @@ TEST(PerfContextTest, StopWatchOverhead) { |
|
|
|
void ProfileKeyComparison() { |
|
|
|
void ProfileKeyComparison() { |
|
|
|
DestroyDB(kDbName, Options()); // Start this test with a fresh DB
|
|
|
|
DestroyDB(kDbName, Options()); // Start this test with a fresh DB
|
|
|
|
|
|
|
|
|
|
|
|
auto db = OpenDb(1000000000); |
|
|
|
auto db = OpenDb(); |
|
|
|
|
|
|
|
|
|
|
|
WriteOptions write_options; |
|
|
|
WriteOptions write_options; |
|
|
|
ReadOptions read_options; |
|
|
|
ReadOptions read_options; |
|
|
@ -77,9 +84,9 @@ void ProfileKeyComparison() { |
|
|
|
uint64_t total_user_key_comparison_put = 0; |
|
|
|
uint64_t total_user_key_comparison_put = 0; |
|
|
|
uint64_t max_user_key_comparison_get = 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 key = "k" + std::to_string(i); |
|
|
|
std::string value = "v" + 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: " |
|
|
|
<< max_user_key_comparison_get << "\n" |
|
|
|
<< max_user_key_comparison_get << "\n" |
|
|
|
<< "avg user key comparison get:" |
|
|
|
<< "avg user key comparison get:" |
|
|
|
<< total_user_key_comparison_get/kTotalKeys << "\n"; |
|
|
|
<< total_user_key_comparison_get/FLAGS_total_keys << "\n"; |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
TEST(PerfContextTest, KeyComparisonCount) { |
|
|
|
TEST(PerfContextTest, KeyComparisonCount) { |
|
|
|
SetPerfLevel(kDisable); |
|
|
|
SetPerfLevel(kEnableCount); |
|
|
|
ProfileKeyComparison(); |
|
|
|
ProfileKeyComparison(); |
|
|
|
|
|
|
|
|
|
|
|
SetPerfLevel(kEnableCount); |
|
|
|
SetPerfLevel(kDisable); |
|
|
|
ProfileKeyComparison(); |
|
|
|
ProfileKeyComparison(); |
|
|
|
|
|
|
|
|
|
|
|
SetPerfLevel(kEnableTime); |
|
|
|
SetPerfLevel(kEnableTime); |
|
|
|
ProfileKeyComparison(); |
|
|
|
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<int> 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<Iterator> 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) { |
|
|
|
int main(int argc, char** argv) { |
|
|
|
|
|
|
|
|
|
|
|
if (argc > 1) { |
|
|
|
for (int i = 1; i < argc; i++) { |
|
|
|
leveldb::kTotalKeys = std::stoi(argv[1]); |
|
|
|
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(); |
|
|
|
leveldb::test::RunAllTests(); |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|