mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
1fdd726 Hotfix RocksDB 3.5 d67500a Add `make install` to Makefile in 3.5.fb. 4cb631a update HISTORY.md cfd0946 comments about the BlockBasedTableOptions migration in Options REVERT: 25888ae Merge pull request #329 from fyrz/master REVERT: 89833e5 Fixed signed-unsigned comparison warning in db_test.cc REVERT: fcac705 Fixed compile warning on Mac caused by unused variables. REVERT: b3343fd resolution for java build problem introduced by 5ec53f3edf62bec1b690ce12fb21a6c52203f3c8 REVERT: 187b299 ForwardIterator: update prev_key_ only if prefix hasn't changed REVERT: 5ec53f3 make compaction related options changeable REVERT: d122e7b Update INSTALL.md REVERT: 986dad0 Merge pull request #324 from dalgaaf/wip-da-SCA-20140930 REVERT: 8ee75dc db/memtable.cc: remove unused variable merge_result REVERT: 0fd8bbc db/db_impl.cc: reduce scope of prefix_initialized REVERT: 676ff7b compaction_picker.cc: remove check for >=0 for unsigned REVERT: e55aea5 document_db.cc: fix assert REVERT: d517c83 in_table_factory.cc: use correct format specifier REVERT: b140375 ttl/ttl_test.cc: prefer prefix ++operator for non-primitive types REVERT: 43c789c spatialdb/spatial_db.cc: use !empty() instead of 'size() > 0' REVERT: 0de452e document_db.cc: pass const parameter by reference REVERT: 4cc8643 util/ldb_cmd.cc: prefer prefix ++operator for non-primitive types REVERT: af8c2b2 util/signal_test.cc: suppress intentional null pointer deref REVERT: 33580fa db/db_impl.cc: fix object handling, remove double lines REVERT: 873f135 db_ttl_impl.h: pass func parameter by reference REVERT: 8558457 ldb_cmd_execute_result.h: perform init in initialization list REVERT: 063471b table/table_test.cc: pass func parameter by reference REVERT: 93548ce table/cuckoo_table_reader.cc: pass func parameter by ref REVERT: b8b7117 db/version_set.cc: use !empty() instead of 'size() > 0' REVERT: 8ce050b table/bloom_block.*: pass func parameter by reference REVERT: 53910dd db_test.cc: pass parameter by reference REVERT: 68ca534 corruption_test.cc: pass parameter by reference REVERT: 7506198 cuckoo_table_db_test.cc: add flush after delete REVERT: 1f96330 Print MB per second compaction throughput separately for reads and writes REVERT: ffe3d49 Add an instruction about SSE in INSTALL.md REVERT: ee1f3cc Package generation for Ubuntu and CentOS REVERT: f0f7955 Fixing comile errors on OS X REVERT: 99fb613 remove 2 space linter REVERT: b2d64a4 Fix linters, second try REVERT: 747523d Print per column family metrics in db_bench REVERT: 56ebd40 Fix arc lint (should fix #238) REVERT: 637f891 Merge pull request #321 from eonnen/master REVERT: 827e31c Make test use a compatible type in the size checks. REVERT: fd5d80d CompactedDB: log using the correct info_log REVERT: 2faf49d use GetContext to replace callback function pointer REVERT: 983d2de Add AUTHORS file. Fix #203 REVERT: abd70c5 Merge pull request #316 from fyrz/ReverseBytewiseComparator REVERT: 2dc6f62 handle kDelete type in cuckoo builder REVERT: 8b8011a Changed name of ReverseBytewiseComparator based on review comment REVERT: 389edb6 universal compaction picker: use double for potential overflow REVERT: 5340484 Built-in comparator(s) in RocksJava REVERT: d439451 delay initialization of cuckoo table iterator REVERT: 94997ea reduce memory usage of cuckoo table builder REVERT: c627595 improve memory efficiency of cuckoo reader REVERT: 581442d option to choose module when calculating CuckooTable hash REVERT: fbd2daf CompactedDBImpl::MultiGet() for better CuckooTable performance REVERT: 3c68006 CompactedDBImpl REVERT: f7375f3 Fix double deletes REVERT: 21ddcf6 Remove allow_thread_local REVERT: fb4a492 Merge pull request #311 from ankgup87/master REVERT: 611e286 Merge branch 'master' of https://github.com/facebook/rocksdb REVERT: 0103b44 Merge branch 'master' of ssh://github.com/ankgup87/rocksdb REVERT: 1dfb7bb Add block based table config options REVERT: cdaf44f Enlarge log size cap when printing file summary REVERT: 7cc1ed7 Merge pull request #309 from naveenatceg/staticbuild REVERT: ba6d660 Resolving merge conflict REVERT: 51eeaf6 Addressing review comments REVERT: fd7d3fe Addressing review comments (adding a env variable to override temp directory) REVERT: cf7ace8 Addressing review comments REVERT: 0a29ce5 re-enable BlockBasedTable::SetupForCompaction() REVERT: 55af370 Remove TODO for checking index checksums REVERT: 3d74f09 Fix compile REVERT: 53b0039 Fix release compile REVERT: d0de413 WriteBatchWithIndex to allow different Comparators for different column families REVERT: 57a32f1 change target_file_size_base to uint64_t REVERT: 5e6aee4 dont create backup_input if compaction filter v2 is not used REVERT: 49b5f94 Merge pull request #306 from Liuchang0812/fix_cast REVERT: 787cb4d remove cast, replace %llu with % PRIu64 REVERT: a7574d4 Update logging.cc REVERT: 7e0dcb9 Update logging.cc REVERT: 57fa3cc Merge pull request #304 from Liuchang0812/fix-check REVERT: cd44522 Merge pull request #305 from Liuchang0812/fix-logging REVERT: 6a031b6 remove unused variable REVERT: 4436f17 fixed #303: replace %ld with % PRId64 REVERT: 7a1bd05 Merge pull request #302 from ankgup87/master REVERT: 423e52c Merge branch 'master' of https://github.com/facebook/rocksdb REVERT: bfeef94 Add rate limiter REVERT: 32f2532 Print compression_size_percent as a signed int REVERT: 976caca Skip AllocateTest if fallocate() is not supported in the file system REVERT: 3b897cd Enable no-fbcode RocksDB build REVERT: f445947 RocksDB: Format uint64 using PRIu64 in db_impl.cc REVERT: e17bc65 Merge pull request #299 from ankgup87/master REVERT: b93797a Fix build REVERT: adae3ca [Java] Fix JNI link error caused by the removal of options.db_stats_log_interval REVERT: 90b8c07 Fix unit tests errors REVERT: 51af7c3 CuckooTable: add one option to allow identity function for the first hash function REVERT: 0350435 Fixed a signed-unsigned comparison in spatial_db.cc -- issue #293 REVERT: 2fb1fea Fix syncronization issues REVERT: ff76895 Remove some unnecessary constructors REVERT: feadb9d fix cuckoo table builder test REVERT: 3c232e1 Fix mac compile REVERT: 54cada9 Run make format on PR #249 REVERT: 27b22f1 Merge pull request #249 from tdfischer/decompression-refactoring REVERT: fb6456b Replace naked calls to operator new and delete (Fixes #222) REVERT: 5600c8f cuckoo table: return estimated size - 1 REVERT: a062e1f SetOptions() for memtable related options REVERT: e4eca6a Options conversion function for convenience REVERT: a7c2094 Merge pull request #292 from saghmrossi/master REVERT: 4d05234 Merge branch 'master' of github.com:saghmrossi/rocksdb REVERT: 60a4aa1 Test use_mmap_reads REVERT: 94e43a1 [Java] Fixed 32-bit overflowing issue when converting jlong to size_t REVERT: f9eaaa6 added include for inttypes.h to fix nonworking printf statements REVERT: f090575 Replaced "built on on earlier work" by "built on earlier work" in README.md REVERT: faad439 Fix #284 REVERT: 49aacd8 Fix make install REVERT: acb9348 [Java] Include WriteBatch into RocksDBSample.java, fix how DbBenchmark.java handles WriteBatch. REVERT: 4a27a2f Don't sync manifest when disableDataSync = true REVERT: 9b8480d Merge pull request #287 from yinqiwen/rate-limiter-crash-fix REVERT: 28be16b fix rate limiter crash #286 REVERT: 04ce1b2 Fix #284 REVERT: add22e3 standardize scripts to run RocksDB benchmarks REVERT: dee91c2 WriteThread REVERT: 540a257 Fix WAL synced REVERT: 24f034b Merge pull request #282 from Chilledheart/develop REVERT: 49fe329 Fix build issue under macosx REVERT: ebb5c65 Add make install REVERT: 0352a9f add_wrapped_bloom_test REVERT: 9c0e66c Don't run background jobs (flush, compactions) when bg_error_ is set REVERT: a9639bd Fix valgrind test REVERT: d1f24dc Relax FlushSchedule test REVERT: 3d9e6f7 Push model for flushing memtables REVERT: 059e584 [unit test] CompactRange should fail if we don't have space REVERT: dd641b2 fix RocksDB java build REVERT: 53404d9 add_qps_info_in cache bench REVERT: a52cecb Fix Mac compile REVERT: 092f97e Fix comments and typos REVERT: 6cc1286 Added a few statistics for BackupableDB REVERT: 0a42295 Fix SimpleWriteTimeoutTest REVERT: 06d9862 Always pass MergeContext as pointer, not reference REVERT: d343c3f Improve db recovery REVERT: 6bb7e3e Merger test REVERT: 88841bd Explicitly cast char to signed char in Hash() REVERT: 5231146 MemTableOptions REVERT: 1d284db Addressing review comments REVERT: 55114e7 Some updates for SpatialDB REVERT: 171d4ff remove TailingIterator reference in db_impl.h REVERT: 9b0f7ff rename version_set options_ to db_options_ to avoid confusion REVERT: 2d57828 Check stop level trigger-0 before slowdown level-0 trigger REVERT: 659d2d5 move compaction_filter to immutable_options REVERT: 048560a reduce references to cfd->options() in DBImpl REVERT: 011241b DB::Flush() Do not wait for background threads when there is nothing in mem table REVERT: a2bb7c3 Push- instead of pull-model for managing Write stalls REVERT: 0af157f Implement full filter for block based table. REVERT: 9360cc6 Fix valgrind issue REVERT: 02d5bff Merge pull request #277 from wankai/master REVERT: 88a2f44 fix comments REVERT: 7c16e39 Merge pull request #276 from wankai/master REVERT: 8237738 replace hard-coded number with named variable REVERT: db8ca52 Merge pull request #273 from nbougalis/static-analysis REVERT: b7b031f Merge pull request #274 from wankai/master REVERT: 4c2b1f0 Merge remote-tracking branch 'upstream/master' REVERT: a5d2863 typo improvement REVERT: 9f8aa09 Don't leak data returned by opendir REVERT: d1cfb71 Remove unused member(s) REVERT: bfee319 sizeof(int*) where sizeof(int) was intended REVERT: d40c1f7 Add missing break statement REVERT: 2e97c38 Avoid off-by-one error when using readlink REVERT: 40ddc3d add cache bench REVERT: 9f1c80b Drop column family from write thread REVERT: 8de151b Add db_bench with lots of column families to regression tests REVERT: c9e419c rename options_ to db_options_ in DBImpl to avoid confusion REVERT: 5cd0576 Fix compaction bug in Cuckoo Table Builder. Use kvs_.size() instead of num_entries in FileSize() method. REVERT: 0fbb3fa fixed memory leak in unit test DBIteratorBoundTest REVERT: adcd253 fix asan check REVERT: 4092b7a Merge pull request #272 from project-zerus/patch-1 REVERT: bb6ae0f fix more compile warnings REVERT: 6d31441 Merge pull request #271 from nbougalis/cleanups REVERT: 0cd0ec4 Plug memory leak during index creation REVERT: 4329d74 Fix swapped variable names to accurately reflect usage REVERT: 45a5e3e Remove path with arena==nullptr from NewInternalIterator REVERT: 5665e5e introduce ImmutableOptions REVERT: e0b99d4 created a new ReadOptions parameter 'iterate_upper_bound' REVERT: 51ea889 Fix travis builds REVERT: a481626 Relax backupable rate limiting test REVERT: f7f973d Merge pull request #269 from huahang/patch-2 REVERT: ef5b384 fix a few compile warnings REVERT: 2fd3806 Merge pull request #263 from wankai/master REVERT: 1785114 delete unused Comparator REVERT: 1b1d961 update HISTORY.md REVERT: 703c3ea comments about the BlockBasedTableOptions migration in Options REVERT: 4b5ad88 Merge pull request #260 from wankai/master REVERT: 19cc588 change to filter_block std::unique_ptr support RAII REVERT: 9b976e3 Merge pull request #259 from wankai/master REVERT: 5d25a46 Merge remote-tracking branch 'upstream/master' REVERT: dff2b1a typo improvement REVERT: 343e98a Reverting import change REVERT: ddb8039 RocksDB static build Make file changes to download and build the dependencies .Load the shared library when RocksDB is initialized git-subtree-dir: src/rocksdb2 git-subtree-split: 1fdd726a8254c13d0c66d8db8130ad17c13d7bcc
538 lines
17 KiB
C++
538 lines
17 KiB
C++
// Copyright (c) 2014, Facebook, Inc. All rights reserved.
|
|
// This source code is licensed under the BSD-style license found in the
|
|
// LICENSE file in the root directory of this source tree. An additional grant
|
|
// of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
#ifndef GFLAGS
|
|
#include <cstdio>
|
|
int main() {
|
|
fprintf(stderr, "Please install gflags to run this test\n");
|
|
return 1;
|
|
}
|
|
#else
|
|
|
|
#define __STDC_FORMAT_MACROS
|
|
#include <inttypes.h>
|
|
#include <gflags/gflags.h>
|
|
#include <vector>
|
|
#include <string>
|
|
#include <map>
|
|
|
|
#include "table/meta_blocks.h"
|
|
#include "table/cuckoo_table_builder.h"
|
|
#include "table/cuckoo_table_reader.h"
|
|
#include "table/cuckoo_table_factory.h"
|
|
#include "util/arena.h"
|
|
#include "util/random.h"
|
|
#include "util/testharness.h"
|
|
#include "util/testutil.h"
|
|
|
|
using GFLAGS::ParseCommandLineFlags;
|
|
using GFLAGS::SetUsageMessage;
|
|
|
|
DEFINE_string(file_dir, "", "Directory where the files will be created"
|
|
" for benchmark. Added for using tmpfs.");
|
|
DEFINE_bool(enable_perf, false, "Run Benchmark Tests too.");
|
|
DEFINE_bool(write, false,
|
|
"Should write new values to file in performance tests?");
|
|
|
|
namespace rocksdb {
|
|
|
|
namespace {
|
|
const uint32_t kNumHashFunc = 10;
|
|
// Methods, variables related to Hash functions.
|
|
std::unordered_map<std::string, std::vector<uint64_t>> hash_map;
|
|
|
|
void AddHashLookups(const std::string& s, uint64_t bucket_id,
|
|
uint32_t num_hash_fun) {
|
|
std::vector<uint64_t> v;
|
|
for (uint32_t i = 0; i < num_hash_fun; i++) {
|
|
v.push_back(bucket_id + i);
|
|
}
|
|
hash_map[s] = v;
|
|
}
|
|
|
|
uint64_t GetSliceHash(const Slice& s, uint32_t index,
|
|
uint64_t max_num_buckets) {
|
|
return hash_map[s.ToString()][index];
|
|
}
|
|
|
|
// Methods, variables for checking key and values read.
|
|
struct ValuesToAssert {
|
|
ValuesToAssert(const std::string& key, const Slice& value)
|
|
: expected_user_key(key),
|
|
expected_value(value),
|
|
call_count(0) {}
|
|
std::string expected_user_key;
|
|
Slice expected_value;
|
|
int call_count;
|
|
};
|
|
|
|
bool AssertValues(void* assert_obj,
|
|
const ParsedInternalKey& k, const Slice& v) {
|
|
ValuesToAssert *ptr = reinterpret_cast<ValuesToAssert*>(assert_obj);
|
|
ASSERT_EQ(ptr->expected_value.ToString(), v.ToString());
|
|
ASSERT_EQ(ptr->expected_user_key, k.user_key.ToString());
|
|
++ptr->call_count;
|
|
return false;
|
|
}
|
|
} // namespace
|
|
|
|
class CuckooReaderTest {
|
|
public:
|
|
CuckooReaderTest() {
|
|
options.allow_mmap_reads = true;
|
|
env = options.env;
|
|
env_options = EnvOptions(options);
|
|
}
|
|
|
|
void SetUp(int num_items) {
|
|
this->num_items = num_items;
|
|
hash_map.clear();
|
|
keys.clear();
|
|
keys.resize(num_items);
|
|
user_keys.clear();
|
|
user_keys.resize(num_items);
|
|
values.clear();
|
|
values.resize(num_items);
|
|
}
|
|
|
|
std::string NumToStr(int64_t i) {
|
|
return std::string(reinterpret_cast<char*>(&i), sizeof(i));
|
|
}
|
|
|
|
void CreateCuckooFileAndCheckReader(
|
|
const Comparator* ucomp = BytewiseComparator()) {
|
|
std::unique_ptr<WritableFile> writable_file;
|
|
ASSERT_OK(env->NewWritableFile(fname, &writable_file, env_options));
|
|
CuckooTableBuilder builder(
|
|
writable_file.get(), 0.9, kNumHashFunc, 100, ucomp, 2, GetSliceHash);
|
|
ASSERT_OK(builder.status());
|
|
for (uint32_t key_idx = 0; key_idx < num_items; ++key_idx) {
|
|
builder.Add(Slice(keys[key_idx]), Slice(values[key_idx]));
|
|
ASSERT_OK(builder.status());
|
|
ASSERT_EQ(builder.NumEntries(), key_idx + 1);
|
|
}
|
|
ASSERT_OK(builder.Finish());
|
|
ASSERT_EQ(num_items, builder.NumEntries());
|
|
file_size = builder.FileSize();
|
|
ASSERT_OK(writable_file->Close());
|
|
|
|
// Check reader now.
|
|
std::unique_ptr<RandomAccessFile> read_file;
|
|
ASSERT_OK(env->NewRandomAccessFile(fname, &read_file, env_options));
|
|
CuckooTableReader reader(
|
|
options,
|
|
std::move(read_file),
|
|
file_size,
|
|
ucomp,
|
|
GetSliceHash);
|
|
ASSERT_OK(reader.status());
|
|
for (uint32_t i = 0; i < num_items; ++i) {
|
|
ValuesToAssert v(user_keys[i], values[i]);
|
|
ASSERT_OK(reader.Get(
|
|
ReadOptions(), Slice(keys[i]), &v, AssertValues, nullptr));
|
|
ASSERT_EQ(1, v.call_count);
|
|
}
|
|
}
|
|
void UpdateKeys(bool with_zero_seqno) {
|
|
for (uint32_t i = 0; i < num_items; i++) {
|
|
ParsedInternalKey ikey(user_keys[i],
|
|
with_zero_seqno ? 0 : i + 1000, kTypeValue);
|
|
keys[i].clear();
|
|
AppendInternalKey(&keys[i], ikey);
|
|
}
|
|
}
|
|
|
|
void CheckIterator(const Comparator* ucomp = BytewiseComparator()) {
|
|
std::unique_ptr<RandomAccessFile> read_file;
|
|
ASSERT_OK(env->NewRandomAccessFile(fname, &read_file, env_options));
|
|
CuckooTableReader reader(
|
|
options,
|
|
std::move(read_file),
|
|
file_size,
|
|
ucomp,
|
|
GetSliceHash);
|
|
ASSERT_OK(reader.status());
|
|
Iterator* it = reader.NewIterator(ReadOptions(), nullptr);
|
|
ASSERT_OK(it->status());
|
|
ASSERT_TRUE(!it->Valid());
|
|
it->SeekToFirst();
|
|
int cnt = 0;
|
|
while (it->Valid()) {
|
|
ASSERT_OK(it->status());
|
|
ASSERT_TRUE(Slice(keys[cnt]) == it->key());
|
|
ASSERT_TRUE(Slice(values[cnt]) == it->value());
|
|
++cnt;
|
|
it->Next();
|
|
}
|
|
ASSERT_EQ(static_cast<uint32_t>(cnt), num_items);
|
|
|
|
it->SeekToLast();
|
|
cnt = num_items - 1;
|
|
ASSERT_TRUE(it->Valid());
|
|
while (it->Valid()) {
|
|
ASSERT_OK(it->status());
|
|
ASSERT_TRUE(Slice(keys[cnt]) == it->key());
|
|
ASSERT_TRUE(Slice(values[cnt]) == it->value());
|
|
--cnt;
|
|
it->Prev();
|
|
}
|
|
ASSERT_EQ(cnt, -1);
|
|
|
|
cnt = num_items / 2;
|
|
it->Seek(keys[cnt]);
|
|
while (it->Valid()) {
|
|
ASSERT_OK(it->status());
|
|
ASSERT_TRUE(Slice(keys[cnt]) == it->key());
|
|
ASSERT_TRUE(Slice(values[cnt]) == it->value());
|
|
++cnt;
|
|
it->Next();
|
|
}
|
|
ASSERT_EQ(static_cast<uint32_t>(cnt), num_items);
|
|
delete it;
|
|
|
|
Arena arena;
|
|
it = reader.NewIterator(ReadOptions(), &arena);
|
|
ASSERT_OK(it->status());
|
|
ASSERT_TRUE(!it->Valid());
|
|
it->Seek(keys[num_items/2]);
|
|
ASSERT_TRUE(it->Valid());
|
|
ASSERT_OK(it->status());
|
|
ASSERT_TRUE(keys[num_items/2] == it->key());
|
|
ASSERT_TRUE(values[num_items/2] == it->value());
|
|
ASSERT_OK(it->status());
|
|
it->~Iterator();
|
|
}
|
|
|
|
std::vector<std::string> keys;
|
|
std::vector<std::string> user_keys;
|
|
std::vector<std::string> values;
|
|
uint64_t num_items;
|
|
std::string fname;
|
|
uint64_t file_size;
|
|
Options options;
|
|
Env* env;
|
|
EnvOptions env_options;
|
|
};
|
|
|
|
TEST(CuckooReaderTest, WhenKeyExists) {
|
|
SetUp(kNumHashFunc);
|
|
fname = test::TmpDir() + "/CuckooReader_WhenKeyExists";
|
|
for (uint64_t i = 0; i < num_items; i++) {
|
|
user_keys[i] = "key" + NumToStr(i);
|
|
ParsedInternalKey ikey(user_keys[i], i + 1000, kTypeValue);
|
|
AppendInternalKey(&keys[i], ikey);
|
|
values[i] = "value" + NumToStr(i);
|
|
// Give disjoint hash values.
|
|
AddHashLookups(user_keys[i], i, kNumHashFunc);
|
|
}
|
|
CreateCuckooFileAndCheckReader();
|
|
// Last level file.
|
|
UpdateKeys(true);
|
|
CreateCuckooFileAndCheckReader();
|
|
// Test with collision. Make all hash values collide.
|
|
hash_map.clear();
|
|
for (uint32_t i = 0; i < num_items; i++) {
|
|
AddHashLookups(user_keys[i], 0, kNumHashFunc);
|
|
}
|
|
UpdateKeys(false);
|
|
CreateCuckooFileAndCheckReader();
|
|
// Last level file.
|
|
UpdateKeys(true);
|
|
CreateCuckooFileAndCheckReader();
|
|
}
|
|
|
|
TEST(CuckooReaderTest, WhenKeyExistsWithUint64Comparator) {
|
|
SetUp(kNumHashFunc);
|
|
fname = test::TmpDir() + "/CuckooReaderUint64_WhenKeyExists";
|
|
for (uint64_t i = 0; i < num_items; i++) {
|
|
user_keys[i].resize(8);
|
|
memcpy(&user_keys[i][0], static_cast<void*>(&i), 8);
|
|
ParsedInternalKey ikey(user_keys[i], i + 1000, kTypeValue);
|
|
AppendInternalKey(&keys[i], ikey);
|
|
values[i] = "value" + NumToStr(i);
|
|
// Give disjoint hash values.
|
|
AddHashLookups(user_keys[i], i, kNumHashFunc);
|
|
}
|
|
CreateCuckooFileAndCheckReader(test::Uint64Comparator());
|
|
// Last level file.
|
|
UpdateKeys(true);
|
|
CreateCuckooFileAndCheckReader(test::Uint64Comparator());
|
|
// Test with collision. Make all hash values collide.
|
|
hash_map.clear();
|
|
for (uint32_t i = 0; i < num_items; i++) {
|
|
AddHashLookups(user_keys[i], 0, kNumHashFunc);
|
|
}
|
|
UpdateKeys(false);
|
|
CreateCuckooFileAndCheckReader(test::Uint64Comparator());
|
|
// Last level file.
|
|
UpdateKeys(true);
|
|
CreateCuckooFileAndCheckReader(test::Uint64Comparator());
|
|
}
|
|
|
|
TEST(CuckooReaderTest, CheckIterator) {
|
|
SetUp(2*kNumHashFunc);
|
|
fname = test::TmpDir() + "/CuckooReader_CheckIterator";
|
|
for (uint64_t i = 0; i < num_items; i++) {
|
|
user_keys[i] = "key" + NumToStr(i);
|
|
ParsedInternalKey ikey(user_keys[i], 1000, kTypeValue);
|
|
AppendInternalKey(&keys[i], ikey);
|
|
values[i] = "value" + NumToStr(i);
|
|
// Give disjoint hash values, in reverse order.
|
|
AddHashLookups(user_keys[i], num_items-i-1, kNumHashFunc);
|
|
}
|
|
CreateCuckooFileAndCheckReader();
|
|
CheckIterator();
|
|
// Last level file.
|
|
UpdateKeys(true);
|
|
CreateCuckooFileAndCheckReader();
|
|
CheckIterator();
|
|
}
|
|
|
|
TEST(CuckooReaderTest, CheckIteratorUint64) {
|
|
SetUp(2*kNumHashFunc);
|
|
fname = test::TmpDir() + "/CuckooReader_CheckIterator";
|
|
for (uint64_t i = 0; i < num_items; i++) {
|
|
user_keys[i].resize(8);
|
|
memcpy(&user_keys[i][0], static_cast<void*>(&i), 8);
|
|
ParsedInternalKey ikey(user_keys[i], 1000, kTypeValue);
|
|
AppendInternalKey(&keys[i], ikey);
|
|
values[i] = "value" + NumToStr(i);
|
|
// Give disjoint hash values, in reverse order.
|
|
AddHashLookups(user_keys[i], num_items-i-1, kNumHashFunc);
|
|
}
|
|
CreateCuckooFileAndCheckReader(test::Uint64Comparator());
|
|
CheckIterator(test::Uint64Comparator());
|
|
// Last level file.
|
|
UpdateKeys(true);
|
|
CreateCuckooFileAndCheckReader(test::Uint64Comparator());
|
|
CheckIterator(test::Uint64Comparator());
|
|
}
|
|
|
|
TEST(CuckooReaderTest, WhenKeyNotFound) {
|
|
// Add keys with colliding hash values.
|
|
SetUp(kNumHashFunc);
|
|
fname = test::TmpDir() + "/CuckooReader_WhenKeyNotFound";
|
|
for (uint64_t i = 0; i < num_items; i++) {
|
|
user_keys[i] = "key" + NumToStr(i);
|
|
ParsedInternalKey ikey(user_keys[i], i + 1000, kTypeValue);
|
|
AppendInternalKey(&keys[i], ikey);
|
|
values[i] = "value" + NumToStr(i);
|
|
// Make all hash values collide.
|
|
AddHashLookups(user_keys[i], 0, kNumHashFunc);
|
|
}
|
|
CreateCuckooFileAndCheckReader();
|
|
std::unique_ptr<RandomAccessFile> read_file;
|
|
ASSERT_OK(env->NewRandomAccessFile(fname, &read_file, env_options));
|
|
CuckooTableReader reader(
|
|
options,
|
|
std::move(read_file),
|
|
file_size,
|
|
BytewiseComparator(),
|
|
GetSliceHash);
|
|
ASSERT_OK(reader.status());
|
|
// Search for a key with colliding hash values.
|
|
std::string not_found_user_key = "key" + NumToStr(num_items);
|
|
std::string not_found_key;
|
|
AddHashLookups(not_found_user_key, 0, kNumHashFunc);
|
|
ParsedInternalKey ikey(not_found_user_key, 1000, kTypeValue);
|
|
AppendInternalKey(¬_found_key, ikey);
|
|
ValuesToAssert v("", "");
|
|
ASSERT_OK(reader.Get(
|
|
ReadOptions(), Slice(not_found_key), &v, AssertValues, nullptr));
|
|
ASSERT_EQ(0, v.call_count);
|
|
ASSERT_OK(reader.status());
|
|
// Search for a key with an independent hash value.
|
|
std::string not_found_user_key2 = "key" + NumToStr(num_items + 1);
|
|
AddHashLookups(not_found_user_key2, kNumHashFunc, kNumHashFunc);
|
|
ParsedInternalKey ikey2(not_found_user_key2, 1000, kTypeValue);
|
|
std::string not_found_key2;
|
|
AppendInternalKey(¬_found_key2, ikey2);
|
|
ASSERT_OK(reader.Get(
|
|
ReadOptions(), Slice(not_found_key2), &v, AssertValues, nullptr));
|
|
ASSERT_EQ(0, v.call_count);
|
|
ASSERT_OK(reader.status());
|
|
|
|
// Test read when key is unused key.
|
|
std::string unused_key =
|
|
reader.GetTableProperties()->user_collected_properties.at(
|
|
CuckooTablePropertyNames::kEmptyKey);
|
|
// Add hash values that map to empty buckets.
|
|
AddHashLookups(ExtractUserKey(unused_key).ToString(),
|
|
kNumHashFunc, kNumHashFunc);
|
|
ASSERT_OK(reader.Get(
|
|
ReadOptions(), Slice(unused_key), &v, AssertValues, nullptr));
|
|
ASSERT_EQ(0, v.call_count);
|
|
ASSERT_OK(reader.status());
|
|
}
|
|
|
|
// Performance tests
|
|
namespace {
|
|
bool DoNothing(void* arg, const ParsedInternalKey& k, const Slice& v) {
|
|
// Deliberately empty.
|
|
return false;
|
|
}
|
|
|
|
bool CheckValue(void* cnt_ptr, const ParsedInternalKey& k, const Slice& v) {
|
|
++*reinterpret_cast<int*>(cnt_ptr);
|
|
std::string expected_value;
|
|
AppendInternalKey(&expected_value, k);
|
|
ASSERT_EQ(0, v.compare(Slice(&expected_value[0], v.size())));
|
|
return false;
|
|
}
|
|
|
|
void GetKeys(uint64_t num, std::vector<std::string>* keys) {
|
|
IterKey k;
|
|
k.SetInternalKey("", 0, kTypeValue);
|
|
std::string internal_key_suffix = k.GetKey().ToString();
|
|
ASSERT_EQ(static_cast<size_t>(8), internal_key_suffix.size());
|
|
for (uint64_t key_idx = 0; key_idx < num; ++key_idx) {
|
|
std::string new_key(reinterpret_cast<char*>(&key_idx), sizeof(key_idx));
|
|
new_key += internal_key_suffix;
|
|
keys->push_back(new_key);
|
|
}
|
|
}
|
|
|
|
std::string GetFileName(uint64_t num) {
|
|
if (FLAGS_file_dir.empty()) {
|
|
FLAGS_file_dir = test::TmpDir();
|
|
}
|
|
return FLAGS_file_dir + "/cuckoo_read_benchmark" +
|
|
std::to_string(num/1000000) + "Mkeys";
|
|
}
|
|
|
|
// Create last level file as we are interested in measuring performance of
|
|
// last level file only.
|
|
void WriteFile(const std::vector<std::string>& keys,
|
|
const uint64_t num, double hash_ratio) {
|
|
Options options;
|
|
options.allow_mmap_reads = true;
|
|
Env* env = options.env;
|
|
EnvOptions env_options = EnvOptions(options);
|
|
std::string fname = GetFileName(num);
|
|
|
|
std::unique_ptr<WritableFile> writable_file;
|
|
ASSERT_OK(env->NewWritableFile(fname, &writable_file, env_options));
|
|
CuckooTableBuilder builder(
|
|
writable_file.get(), hash_ratio,
|
|
64, 1000, test::Uint64Comparator(), 5, nullptr);
|
|
ASSERT_OK(builder.status());
|
|
for (uint64_t key_idx = 0; key_idx < num; ++key_idx) {
|
|
// Value is just a part of key.
|
|
builder.Add(Slice(keys[key_idx]), Slice(&keys[key_idx][0], 4));
|
|
ASSERT_EQ(builder.NumEntries(), key_idx + 1);
|
|
ASSERT_OK(builder.status());
|
|
}
|
|
ASSERT_OK(builder.Finish());
|
|
ASSERT_EQ(num, builder.NumEntries());
|
|
ASSERT_OK(writable_file->Close());
|
|
|
|
uint64_t file_size;
|
|
env->GetFileSize(fname, &file_size);
|
|
std::unique_ptr<RandomAccessFile> read_file;
|
|
ASSERT_OK(env->NewRandomAccessFile(fname, &read_file, env_options));
|
|
|
|
CuckooTableReader reader(
|
|
options, std::move(read_file), file_size,
|
|
test::Uint64Comparator(), nullptr);
|
|
ASSERT_OK(reader.status());
|
|
ReadOptions r_options;
|
|
for (uint64_t i = 0; i < num; ++i) {
|
|
int cnt = 0;
|
|
ASSERT_OK(reader.Get(r_options, Slice(keys[i]), &cnt, CheckValue, nullptr));
|
|
if (cnt != 1) {
|
|
fprintf(stderr, "%" PRIu64 " not found.\n", i);
|
|
ASSERT_EQ(1, cnt);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ReadKeys(uint64_t num, uint32_t batch_size) {
|
|
Options options;
|
|
options.allow_mmap_reads = true;
|
|
Env* env = options.env;
|
|
EnvOptions env_options = EnvOptions(options);
|
|
std::string fname = GetFileName(num);
|
|
|
|
uint64_t file_size;
|
|
env->GetFileSize(fname, &file_size);
|
|
std::unique_ptr<RandomAccessFile> read_file;
|
|
ASSERT_OK(env->NewRandomAccessFile(fname, &read_file, env_options));
|
|
|
|
CuckooTableReader reader(
|
|
options, std::move(read_file), file_size, test::Uint64Comparator(),
|
|
nullptr);
|
|
ASSERT_OK(reader.status());
|
|
const UserCollectedProperties user_props =
|
|
reader.GetTableProperties()->user_collected_properties;
|
|
const uint32_t num_hash_fun = *reinterpret_cast<const uint32_t*>(
|
|
user_props.at(CuckooTablePropertyNames::kNumHashFunc).data());
|
|
const uint64_t table_size = *reinterpret_cast<const uint64_t*>(
|
|
user_props.at(CuckooTablePropertyNames::kHashTableSize).data());
|
|
fprintf(stderr, "With %" PRIu64 " items, utilization is %.2f%%, number of"
|
|
" hash functions: %u.\n", num, num * 100.0 / (table_size), num_hash_fun);
|
|
ReadOptions r_options;
|
|
|
|
uint64_t start_time = env->NowMicros();
|
|
if (batch_size > 0) {
|
|
for (uint64_t i = 0; i < num; i += batch_size) {
|
|
for (uint64_t j = i; j < i+batch_size && j < num; ++j) {
|
|
reader.Prepare(Slice(reinterpret_cast<char*>(&j), 16));
|
|
}
|
|
for (uint64_t j = i; j < i+batch_size && j < num; ++j) {
|
|
reader.Get(r_options, Slice(reinterpret_cast<char*>(&j), 16),
|
|
nullptr, DoNothing, nullptr);
|
|
}
|
|
}
|
|
} else {
|
|
for (uint64_t i = 0; i < num; i++) {
|
|
reader.Get(r_options, Slice(reinterpret_cast<char*>(&i), 16), nullptr,
|
|
DoNothing, nullptr);
|
|
}
|
|
}
|
|
float time_per_op = (env->NowMicros() - start_time) * 1.0 / num;
|
|
fprintf(stderr,
|
|
"Time taken per op is %.3fus (%.1f Mqps) with batch size of %u\n",
|
|
time_per_op, 1.0 / time_per_op, batch_size);
|
|
}
|
|
} // namespace.
|
|
|
|
TEST(CuckooReaderTest, TestReadPerformance) {
|
|
if (!FLAGS_enable_perf) {
|
|
return;
|
|
}
|
|
double hash_ratio = 0.95;
|
|
// These numbers are chosen to have a hash utilizaiton % close to
|
|
// 0.9, 0.75, 0.6 and 0.5 respectively.
|
|
// They all create 128 M buckets.
|
|
std::vector<uint64_t> nums = {120*1000*1000, 100*1000*1000, 80*1000*1000,
|
|
70*1000*1000};
|
|
#ifndef NDEBUG
|
|
fprintf(stdout,
|
|
"WARNING: Not compiled with DNDEBUG. Performance tests may be slow.\n");
|
|
#endif
|
|
std::vector<std::string> keys;
|
|
GetKeys(*std::max_element(nums.begin(), nums.end()), &keys);
|
|
for (uint64_t num : nums) {
|
|
if (FLAGS_write || !Env::Default()->FileExists(GetFileName(num))) {
|
|
WriteFile(keys, num, hash_ratio);
|
|
}
|
|
ReadKeys(num, 0);
|
|
ReadKeys(num, 10);
|
|
ReadKeys(num, 25);
|
|
ReadKeys(num, 50);
|
|
ReadKeys(num, 100);
|
|
fprintf(stderr, "\n");
|
|
}
|
|
}
|
|
} // namespace rocksdb
|
|
|
|
int main(int argc, char** argv) {
|
|
ParseCommandLineFlags(&argc, &argv, true);
|
|
rocksdb::test::RunAllTests();
|
|
return 0;
|
|
}
|
|
|
|
#endif // GFLAGS.
|