@nxtedition/rocksdb 7.1.25 → 7.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/deps/rocksdb/rocksdb/cache/clock_cache.cc +7 -4
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +18 -2
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +5 -1
- package/deps/rocksdb/rocksdb/db/db_iter.cc +2 -1
- package/deps/rocksdb/rocksdb/db/db_test_util.cc +4 -2
- package/deps/rocksdb/rocksdb/db/db_test_util.h +1 -1
- package/deps/rocksdb/rocksdb/db/version_set.cc +1 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/block_cache_trace_writer.h +149 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/db.h +8 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/table.h +1 -1
- package/deps/rocksdb/rocksdb/{table → include/rocksdb}/table_reader_caller.h +0 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/stackable_db.h +7 -1
- package/deps/rocksdb/rocksdb/table/table_reader.h +1 -1
- package/deps/rocksdb/rocksdb/table/table_test.cc +29 -22
- package/deps/rocksdb/rocksdb/tools/block_cache_analyzer/block_cache_trace_analyzer.cc +1 -1
- package/deps/rocksdb/rocksdb/tools/block_cache_analyzer/block_cache_trace_analyzer.h +1 -1
- package/deps/rocksdb/rocksdb/tools/block_cache_analyzer/block_cache_trace_analyzer_test.cc +25 -16
- package/deps/rocksdb/rocksdb/trace_replay/block_cache_tracer.cc +28 -21
- package/deps/rocksdb/rocksdb/trace_replay/block_cache_tracer.h +16 -72
- package/deps/rocksdb/rocksdb/trace_replay/block_cache_tracer_test.cc +74 -38
- package/deps/rocksdb/rocksdb/util/user_comparator_wrapper.h +11 -31
- package/deps/rocksdb/rocksdb/utilities/simulator_cache/cache_simulator.cc +2 -2
- package/deps/rocksdb/rocksdb/utilities/simulator_cache/cache_simulator_test.cc +13 -13
- package/deps/rocksdb/rocksdb.gyp +1 -0
- package/package.json +1 -1
- package/prebuilds/darwin-arm64/node.napi.node +0 -0
- package/prebuilds/linux-x64/node.napi.node +0 -0
|
@@ -919,11 +919,13 @@ void ClockHandleTable::Evict(size_t requested_charge, size_t* freed_charge,
|
|
|
919
919
|
uint64_t{ClockHandle::kStateConstruction}
|
|
920
920
|
<< ClockHandle::kStateShift,
|
|
921
921
|
std::memory_order_acquire)) {
|
|
922
|
-
// Took ownership
|
|
923
|
-
|
|
922
|
+
// Took ownership.
|
|
923
|
+
// Save info about h to minimize dependences between atomic updates
|
|
924
|
+
// (e.g. fully relaxed Rollback after h released by marking empty)
|
|
925
|
+
const UniqueId64x2 h_hashed_key = h.hashed_key;
|
|
926
|
+
size_t h_total_charge = h.total_charge;
|
|
924
927
|
// TODO? Delay freeing?
|
|
925
928
|
h.FreeData();
|
|
926
|
-
*freed_charge += h.total_charge;
|
|
927
929
|
#ifndef NDEBUG
|
|
928
930
|
// Mark slot as empty, with assertion
|
|
929
931
|
meta = h.meta.exchange(0, std::memory_order_release);
|
|
@@ -934,7 +936,8 @@ void ClockHandleTable::Evict(size_t requested_charge, size_t* freed_charge,
|
|
|
934
936
|
h.meta.store(0, std::memory_order_release);
|
|
935
937
|
#endif
|
|
936
938
|
*freed_count += 1;
|
|
937
|
-
|
|
939
|
+
*freed_charge += h_total_charge;
|
|
940
|
+
Rollback(h_hashed_key, &h);
|
|
938
941
|
}
|
|
939
942
|
}
|
|
940
943
|
|
|
@@ -5782,8 +5782,24 @@ Status DBImpl::NewDefaultReplayer(
|
|
|
5782
5782
|
Status DBImpl::StartBlockCacheTrace(
|
|
5783
5783
|
const TraceOptions& trace_options,
|
|
5784
5784
|
std::unique_ptr<TraceWriter>&& trace_writer) {
|
|
5785
|
-
|
|
5786
|
-
|
|
5785
|
+
BlockCacheTraceOptions block_trace_opts;
|
|
5786
|
+
block_trace_opts.sampling_frequency = trace_options.sampling_frequency;
|
|
5787
|
+
|
|
5788
|
+
BlockCacheTraceWriterOptions trace_writer_opt;
|
|
5789
|
+
trace_writer_opt.max_trace_file_size = trace_options.max_trace_file_size;
|
|
5790
|
+
|
|
5791
|
+
std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
|
|
5792
|
+
NewBlockCacheTraceWriter(env_->GetSystemClock().get(), trace_writer_opt,
|
|
5793
|
+
std::move(trace_writer));
|
|
5794
|
+
|
|
5795
|
+
return block_cache_tracer_.StartTrace(block_trace_opts,
|
|
5796
|
+
std::move(block_cache_trace_writer));
|
|
5797
|
+
}
|
|
5798
|
+
|
|
5799
|
+
Status DBImpl::StartBlockCacheTrace(
|
|
5800
|
+
const BlockCacheTraceOptions& trace_options,
|
|
5801
|
+
std::unique_ptr<BlockCacheTraceWriter>&& trace_writer) {
|
|
5802
|
+
return block_cache_tracer_.StartTrace(trace_options, std::move(trace_writer));
|
|
5787
5803
|
}
|
|
5788
5804
|
|
|
5789
5805
|
Status DBImpl::EndBlockCacheTrace() {
|
|
@@ -568,9 +568,13 @@ class DBImpl : public DB {
|
|
|
568
568
|
|
|
569
569
|
using DB::StartBlockCacheTrace;
|
|
570
570
|
Status StartBlockCacheTrace(
|
|
571
|
-
const TraceOptions&
|
|
571
|
+
const TraceOptions& trace_options,
|
|
572
572
|
std::unique_ptr<TraceWriter>&& trace_writer) override;
|
|
573
573
|
|
|
574
|
+
Status StartBlockCacheTrace(
|
|
575
|
+
const BlockCacheTraceOptions& options,
|
|
576
|
+
std::unique_ptr<BlockCacheTraceWriter>&& trace_writer) override;
|
|
577
|
+
|
|
574
578
|
using DB::EndBlockCacheTrace;
|
|
575
579
|
Status EndBlockCacheTrace() override;
|
|
576
580
|
|
|
@@ -90,7 +90,8 @@ DBIter::DBIter(Env* _env, const ReadOptions& read_options,
|
|
|
90
90
|
iter_.iter()->SetPinnedItersMgr(&pinned_iters_mgr_);
|
|
91
91
|
}
|
|
92
92
|
status_.PermitUncheckedError();
|
|
93
|
-
assert(timestamp_size_ ==
|
|
93
|
+
assert(timestamp_size_ ==
|
|
94
|
+
user_comparator_.user_comparator()->timestamp_size());
|
|
94
95
|
}
|
|
95
96
|
|
|
96
97
|
Status DBIter::GetProperty(std::string prop_name, std::string* prop) {
|
|
@@ -487,8 +487,10 @@ Options DBTestBase::GetOptions(
|
|
|
487
487
|
case kInfiniteMaxOpenFiles:
|
|
488
488
|
options.max_open_files = -1;
|
|
489
489
|
break;
|
|
490
|
-
case
|
|
491
|
-
|
|
490
|
+
case kCRC32cChecksum: {
|
|
491
|
+
// Old default was CRC32c, but XXH3 (new default) is faster on common
|
|
492
|
+
// hardware
|
|
493
|
+
table_options.checksum = kCRC32c;
|
|
492
494
|
// Thrown in here for basic coverage:
|
|
493
495
|
options.DisableExtraChecks();
|
|
494
496
|
break;
|
|
@@ -1048,7 +1048,7 @@ class DBTestBase : public testing::Test {
|
|
|
1048
1048
|
kUniversalCompactionMultiLevel = 20,
|
|
1049
1049
|
kCompressedBlockCache = 21,
|
|
1050
1050
|
kInfiniteMaxOpenFiles = 22,
|
|
1051
|
-
|
|
1051
|
+
kCRC32cChecksum = 23,
|
|
1052
1052
|
kFIFOCompaction = 24,
|
|
1053
1053
|
kOptimizeFiltersForHits = 25,
|
|
1054
1054
|
kRowCache = 26,
|
|
@@ -1239,7 +1239,7 @@ void LevelIterator::Seek(const Slice& target) {
|
|
|
1239
1239
|
prefix_extractor_ != nullptr && !read_options_.total_order_seek &&
|
|
1240
1240
|
!read_options_.auto_prefix_mode &&
|
|
1241
1241
|
file_index_ < flevel_->num_files - 1) {
|
|
1242
|
-
size_t ts_sz = user_comparator_.timestamp_size();
|
|
1242
|
+
size_t ts_sz = user_comparator_.user_comparator()->timestamp_size();
|
|
1243
1243
|
Slice target_user_key_without_ts =
|
|
1244
1244
|
ExtractUserKeyAndStripTimestamp(target, ts_sz);
|
|
1245
1245
|
Slice next_file_first_user_key_without_ts =
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// Copyright (c) 2022, Meta, Inc. All rights reserved.
|
|
2
|
+
// This source code is licensed under both the GPLv2 (found in the
|
|
3
|
+
// COPYING file in the root directory) and Apache 2.0 License
|
|
4
|
+
// (found in the LICENSE.Apache file in the root directory).
|
|
5
|
+
|
|
6
|
+
#pragma once
|
|
7
|
+
|
|
8
|
+
#include "rocksdb/options.h"
|
|
9
|
+
#include "rocksdb/system_clock.h"
|
|
10
|
+
#include "rocksdb/table_reader_caller.h"
|
|
11
|
+
#include "rocksdb/trace_reader_writer.h"
|
|
12
|
+
#include "rocksdb/trace_record.h"
|
|
13
|
+
|
|
14
|
+
namespace ROCKSDB_NAMESPACE {
|
|
15
|
+
// A record for block cache lookups/inserts. This is passed by the table
|
|
16
|
+
// reader to the BlockCacheTraceWriter for every block cache op.
|
|
17
|
+
struct BlockCacheTraceRecord {
|
|
18
|
+
// Required fields for all accesses.
|
|
19
|
+
uint64_t access_timestamp = 0;
|
|
20
|
+
|
|
21
|
+
// Info related to the block being looked up or inserted
|
|
22
|
+
//
|
|
23
|
+
// 1. The cache key for the block
|
|
24
|
+
std::string block_key;
|
|
25
|
+
|
|
26
|
+
// 2. The type of block
|
|
27
|
+
TraceType block_type = TraceType::kTraceMax;
|
|
28
|
+
|
|
29
|
+
// 3. Size of the block
|
|
30
|
+
uint64_t block_size = 0;
|
|
31
|
+
|
|
32
|
+
// Info about the SST file the block is in
|
|
33
|
+
//
|
|
34
|
+
// 1. Column family ID
|
|
35
|
+
uint64_t cf_id = 0;
|
|
36
|
+
|
|
37
|
+
// 2. Column family name
|
|
38
|
+
std::string cf_name;
|
|
39
|
+
|
|
40
|
+
// 3. LSM level of the file
|
|
41
|
+
uint32_t level = 0;
|
|
42
|
+
|
|
43
|
+
// 4. SST file number
|
|
44
|
+
uint64_t sst_fd_number = 0;
|
|
45
|
+
|
|
46
|
+
// Info about the calling context
|
|
47
|
+
//
|
|
48
|
+
// 1. The higher level request triggering the block cache request
|
|
49
|
+
TableReaderCaller caller = TableReaderCaller::kMaxBlockCacheLookupCaller;
|
|
50
|
+
|
|
51
|
+
// 2. Cache lookup hit/miss. Not relevant for inserts
|
|
52
|
+
bool is_cache_hit = false;
|
|
53
|
+
|
|
54
|
+
// 3. Whether this request is a lookup
|
|
55
|
+
bool no_insert = false;
|
|
56
|
+
|
|
57
|
+
// Get/MultiGet specific info
|
|
58
|
+
//
|
|
59
|
+
// 1. A unique ID for Get/MultiGet
|
|
60
|
+
uint64_t get_id = kReservedGetId;
|
|
61
|
+
|
|
62
|
+
// 2. Whether the Get/MultiGet is from a user-specified snapshot
|
|
63
|
+
bool get_from_user_specified_snapshot = false;
|
|
64
|
+
|
|
65
|
+
// 3. The target user key in the block
|
|
66
|
+
std::string referenced_key;
|
|
67
|
+
|
|
68
|
+
// Required fields for data block and user Get/Multi-Get only.
|
|
69
|
+
//
|
|
70
|
+
// 1. Size of te useful data in the block
|
|
71
|
+
uint64_t referenced_data_size = 0;
|
|
72
|
+
|
|
73
|
+
// 2. Only for MultiGet, number of keys from the batch found in the block
|
|
74
|
+
uint64_t num_keys_in_block = 0;
|
|
75
|
+
|
|
76
|
+
// 3. Whether the key was found in the block or not (false positive)
|
|
77
|
+
bool referenced_key_exist_in_block = false;
|
|
78
|
+
|
|
79
|
+
static const uint64_t kReservedGetId;
|
|
80
|
+
|
|
81
|
+
BlockCacheTraceRecord() {}
|
|
82
|
+
|
|
83
|
+
BlockCacheTraceRecord(uint64_t _access_timestamp, std::string _block_key,
|
|
84
|
+
TraceType _block_type, uint64_t _block_size,
|
|
85
|
+
uint64_t _cf_id, std::string _cf_name, uint32_t _level,
|
|
86
|
+
uint64_t _sst_fd_number, TableReaderCaller _caller,
|
|
87
|
+
bool _is_cache_hit, bool _no_insert, uint64_t _get_id,
|
|
88
|
+
bool _get_from_user_specified_snapshot = false,
|
|
89
|
+
std::string _referenced_key = "",
|
|
90
|
+
uint64_t _referenced_data_size = 0,
|
|
91
|
+
uint64_t _num_keys_in_block = 0,
|
|
92
|
+
bool _referenced_key_exist_in_block = false)
|
|
93
|
+
: access_timestamp(_access_timestamp),
|
|
94
|
+
block_key(_block_key),
|
|
95
|
+
block_type(_block_type),
|
|
96
|
+
block_size(_block_size),
|
|
97
|
+
cf_id(_cf_id),
|
|
98
|
+
cf_name(_cf_name),
|
|
99
|
+
level(_level),
|
|
100
|
+
sst_fd_number(_sst_fd_number),
|
|
101
|
+
caller(_caller),
|
|
102
|
+
is_cache_hit(_is_cache_hit),
|
|
103
|
+
no_insert(_no_insert),
|
|
104
|
+
get_id(_get_id),
|
|
105
|
+
get_from_user_specified_snapshot(_get_from_user_specified_snapshot),
|
|
106
|
+
referenced_key(_referenced_key),
|
|
107
|
+
referenced_data_size(_referenced_data_size),
|
|
108
|
+
num_keys_in_block(_num_keys_in_block),
|
|
109
|
+
referenced_key_exist_in_block(_referenced_key_exist_in_block) {}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
// Options for tracing block cache accesses
|
|
113
|
+
struct BlockCacheTraceOptions {
|
|
114
|
+
// Specify trace sampling option, i.e. capture one per how many requests.
|
|
115
|
+
// Default to 1 (capture every request).
|
|
116
|
+
uint64_t sampling_frequency = 1;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Options for the built-in implementation of BlockCacheTraceWriter
|
|
120
|
+
struct BlockCacheTraceWriterOptions {
|
|
121
|
+
uint64_t max_trace_file_size = uint64_t{64} * 1024 * 1024 * 1024;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
// BlockCacheTraceWriter is an abstract class that captures all RocksDB block
|
|
125
|
+
// cache accesses. Every RocksDB operation is passed to WriteBlockAccess()
|
|
126
|
+
// with a BlockCacheTraceRecord.
|
|
127
|
+
class BlockCacheTraceWriter {
|
|
128
|
+
public:
|
|
129
|
+
virtual ~BlockCacheTraceWriter() {}
|
|
130
|
+
|
|
131
|
+
// Pass Slice references to avoid copy.
|
|
132
|
+
virtual Status WriteBlockAccess(const BlockCacheTraceRecord& record,
|
|
133
|
+
const Slice& block_key, const Slice& cf_name,
|
|
134
|
+
const Slice& referenced_key) = 0;
|
|
135
|
+
|
|
136
|
+
// Write a trace header at the beginning, typically on initiating a trace,
|
|
137
|
+
// with some metadata like a magic number and RocksDB version.
|
|
138
|
+
virtual Status WriteHeader() = 0;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
// Allocate an instance of the built-in BlockCacheTraceWriter implementation,
|
|
142
|
+
// that traces all block cache accesses to a user-provided TraceWriter. Each
|
|
143
|
+
// access is traced to a file with a timestamp and type, followed by the
|
|
144
|
+
// payload.
|
|
145
|
+
std::unique_ptr<BlockCacheTraceWriter> NewBlockCacheTraceWriter(
|
|
146
|
+
SystemClock* clock, const BlockCacheTraceWriterOptions& trace_options,
|
|
147
|
+
std::unique_ptr<TraceWriter>&& trace_writer);
|
|
148
|
+
|
|
149
|
+
} // namespace ROCKSDB_NAMESPACE
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
#include <unordered_map>
|
|
18
18
|
#include <vector>
|
|
19
19
|
|
|
20
|
+
#include "rocksdb/block_cache_trace_writer.h"
|
|
20
21
|
#include "rocksdb/iterator.h"
|
|
21
22
|
#include "rocksdb/listener.h"
|
|
22
23
|
#include "rocksdb/metadata.h"
|
|
@@ -1748,11 +1749,17 @@ class DB {
|
|
|
1748
1749
|
|
|
1749
1750
|
// Trace block cache accesses. Use EndBlockCacheTrace() to stop tracing.
|
|
1750
1751
|
virtual Status StartBlockCacheTrace(
|
|
1751
|
-
const TraceOptions& /*
|
|
1752
|
+
const TraceOptions& /*trace_options*/,
|
|
1752
1753
|
std::unique_ptr<TraceWriter>&& /*trace_writer*/) {
|
|
1753
1754
|
return Status::NotSupported("StartBlockCacheTrace() is not implemented.");
|
|
1754
1755
|
}
|
|
1755
1756
|
|
|
1757
|
+
virtual Status StartBlockCacheTrace(
|
|
1758
|
+
const BlockCacheTraceOptions& /*options*/,
|
|
1759
|
+
std::unique_ptr<BlockCacheTraceWriter>&& /*trace_writer*/) {
|
|
1760
|
+
return Status::NotSupported("StartBlockCacheTrace() is not implemented.");
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1756
1763
|
virtual Status EndBlockCacheTrace() {
|
|
1757
1764
|
return Status::NotSupported("EndBlockCacheTrace() is not implemented.");
|
|
1758
1765
|
}
|
|
@@ -251,7 +251,7 @@ struct BlockBasedTableOptions {
|
|
|
251
251
|
// Use the specified checksum type. Newly created table files will be
|
|
252
252
|
// protected with this checksum type. Old table files will still be readable,
|
|
253
253
|
// even though they have different checksum type.
|
|
254
|
-
ChecksumType checksum =
|
|
254
|
+
ChecksumType checksum = kXXH3;
|
|
255
255
|
|
|
256
256
|
// Disable block cache. If this is set to true,
|
|
257
257
|
// then no block cache should be used, and the block_cache should
|
|
File without changes
|
|
@@ -404,8 +404,14 @@ class StackableDB : public DB {
|
|
|
404
404
|
|
|
405
405
|
using DB::StartBlockCacheTrace;
|
|
406
406
|
Status StartBlockCacheTrace(
|
|
407
|
-
const TraceOptions&
|
|
407
|
+
const TraceOptions& trace_options,
|
|
408
408
|
std::unique_ptr<TraceWriter>&& trace_writer) override {
|
|
409
|
+
return db_->StartBlockCacheTrace(trace_options, std::move(trace_writer));
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
Status StartBlockCacheTrace(
|
|
413
|
+
const BlockCacheTraceOptions& options,
|
|
414
|
+
std::unique_ptr<BlockCacheTraceWriter>&& trace_writer) override {
|
|
409
415
|
return db_->StartBlockCacheTrace(options, std::move(trace_writer));
|
|
410
416
|
}
|
|
411
417
|
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
#include "folly/experimental/coro/Task.h"
|
|
16
16
|
#endif
|
|
17
17
|
#include "rocksdb/slice_transform.h"
|
|
18
|
+
#include "rocksdb/table_reader_caller.h"
|
|
18
19
|
#include "table/get_context.h"
|
|
19
20
|
#include "table/internal_iterator.h"
|
|
20
21
|
#include "table/multiget_context.h"
|
|
21
|
-
#include "table/table_reader_caller.h"
|
|
22
22
|
|
|
23
23
|
namespace ROCKSDB_NAMESPACE {
|
|
24
24
|
|
|
@@ -1147,15 +1147,21 @@ class BlockBasedTableTest
|
|
|
1147
1147
|
test_path_ = test::PerThreadDBPath("block_based_table_tracing_test");
|
|
1148
1148
|
EXPECT_OK(env_->CreateDir(test_path_));
|
|
1149
1149
|
trace_file_path_ = test_path_ + "/block_cache_trace_file";
|
|
1150
|
-
|
|
1150
|
+
|
|
1151
|
+
BlockCacheTraceWriterOptions trace_writer_opt;
|
|
1152
|
+
BlockCacheTraceOptions trace_opt;
|
|
1151
1153
|
std::unique_ptr<TraceWriter> trace_writer;
|
|
1152
1154
|
EXPECT_OK(NewFileTraceWriter(env_, EnvOptions(), trace_file_path_,
|
|
1153
1155
|
&trace_writer));
|
|
1156
|
+
std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
|
|
1157
|
+
NewBlockCacheTraceWriter(env_->GetSystemClock().get(), trace_writer_opt,
|
|
1158
|
+
std::move(trace_writer));
|
|
1159
|
+
ASSERT_NE(block_cache_trace_writer, nullptr);
|
|
1154
1160
|
// Always return Status::OK().
|
|
1155
1161
|
assert(c->block_cache_tracer_
|
|
1156
|
-
.StartTrace(
|
|
1157
|
-
std::move(trace_writer))
|
|
1162
|
+
.StartTrace(trace_opt, std::move(block_cache_trace_writer))
|
|
1158
1163
|
.ok());
|
|
1164
|
+
|
|
1159
1165
|
{
|
|
1160
1166
|
std::string user_key = "k01";
|
|
1161
1167
|
InternalKey internal_key(user_key, 0, kTypeValue);
|
|
@@ -1213,10 +1219,10 @@ class BlockBasedTableTest
|
|
|
1213
1219
|
} else {
|
|
1214
1220
|
EXPECT_EQ(access.referenced_key, "");
|
|
1215
1221
|
EXPECT_EQ(access.get_id, 0);
|
|
1216
|
-
|
|
1222
|
+
EXPECT_FALSE(access.get_from_user_specified_snapshot);
|
|
1217
1223
|
EXPECT_EQ(access.referenced_data_size, 0);
|
|
1218
1224
|
EXPECT_EQ(access.num_keys_in_block, 0);
|
|
1219
|
-
|
|
1225
|
+
EXPECT_FALSE(access.referenced_key_exist_in_block);
|
|
1220
1226
|
}
|
|
1221
1227
|
index++;
|
|
1222
1228
|
}
|
|
@@ -2250,7 +2256,8 @@ TEST_P(BlockBasedTableTest, BadChecksumType) {
|
|
|
2250
2256
|
// Corrupt checksum type (123 is invalid)
|
|
2251
2257
|
auto& sink = *c.TEST_GetSink();
|
|
2252
2258
|
size_t len = sink.contents_.size();
|
|
2253
|
-
ASSERT_EQ(sink.contents_[len - Footer::kNewVersionsEncodedLength],
|
|
2259
|
+
ASSERT_EQ(sink.contents_[len - Footer::kNewVersionsEncodedLength],
|
|
2260
|
+
table_options.checksum);
|
|
2254
2261
|
sink.contents_[len - Footer::kNewVersionsEncodedLength] = char{123};
|
|
2255
2262
|
|
|
2256
2263
|
// (Re-)Open table file with bad checksum type
|
|
@@ -3051,8 +3058,8 @@ TEST_P(BlockBasedTableTest, TracingGetTest) {
|
|
|
3051
3058
|
BlockCacheTraceRecord record;
|
|
3052
3059
|
record.block_type = TraceType::kBlockTraceIndexBlock;
|
|
3053
3060
|
record.caller = TableReaderCaller::kPrefetch;
|
|
3054
|
-
record.is_cache_hit =
|
|
3055
|
-
record.no_insert =
|
|
3061
|
+
record.is_cache_hit = false;
|
|
3062
|
+
record.no_insert = false;
|
|
3056
3063
|
expected_records.push_back(record);
|
|
3057
3064
|
record.block_type = TraceType::kBlockTraceFilterBlock;
|
|
3058
3065
|
expected_records.push_back(record);
|
|
@@ -3061,22 +3068,22 @@ TEST_P(BlockBasedTableTest, TracingGetTest) {
|
|
|
3061
3068
|
record.get_id = 1;
|
|
3062
3069
|
record.block_type = TraceType::kBlockTraceFilterBlock;
|
|
3063
3070
|
record.caller = TableReaderCaller::kUserGet;
|
|
3064
|
-
record.get_from_user_specified_snapshot =
|
|
3071
|
+
record.get_from_user_specified_snapshot = false;
|
|
3065
3072
|
record.referenced_key = encoded_key;
|
|
3066
|
-
record.referenced_key_exist_in_block =
|
|
3067
|
-
record.is_cache_hit =
|
|
3073
|
+
record.referenced_key_exist_in_block = true;
|
|
3074
|
+
record.is_cache_hit = true;
|
|
3068
3075
|
expected_records.push_back(record);
|
|
3069
3076
|
record.block_type = TraceType::kBlockTraceIndexBlock;
|
|
3070
3077
|
expected_records.push_back(record);
|
|
3071
|
-
record.is_cache_hit =
|
|
3078
|
+
record.is_cache_hit = false;
|
|
3072
3079
|
record.block_type = TraceType::kBlockTraceDataBlock;
|
|
3073
3080
|
expected_records.push_back(record);
|
|
3074
3081
|
// The second get should all observe cache hits.
|
|
3075
|
-
record.is_cache_hit =
|
|
3082
|
+
record.is_cache_hit = true;
|
|
3076
3083
|
record.get_id = 2;
|
|
3077
3084
|
record.block_type = TraceType::kBlockTraceFilterBlock;
|
|
3078
3085
|
record.caller = TableReaderCaller::kUserGet;
|
|
3079
|
-
record.get_from_user_specified_snapshot =
|
|
3086
|
+
record.get_from_user_specified_snapshot = false;
|
|
3080
3087
|
record.referenced_key = encoded_key;
|
|
3081
3088
|
expected_records.push_back(record);
|
|
3082
3089
|
record.block_type = TraceType::kBlockTraceIndexBlock;
|
|
@@ -3116,15 +3123,15 @@ TEST_P(BlockBasedTableTest, TracingApproximateOffsetOfTest) {
|
|
|
3116
3123
|
BlockCacheTraceRecord record;
|
|
3117
3124
|
record.block_type = TraceType::kBlockTraceIndexBlock;
|
|
3118
3125
|
record.caller = TableReaderCaller::kPrefetch;
|
|
3119
|
-
record.is_cache_hit =
|
|
3120
|
-
record.no_insert =
|
|
3126
|
+
record.is_cache_hit = false;
|
|
3127
|
+
record.no_insert = false;
|
|
3121
3128
|
expected_records.push_back(record);
|
|
3122
3129
|
record.block_type = TraceType::kBlockTraceFilterBlock;
|
|
3123
3130
|
expected_records.push_back(record);
|
|
3124
3131
|
// Then we should have two records for only index blocks.
|
|
3125
3132
|
record.block_type = TraceType::kBlockTraceIndexBlock;
|
|
3126
3133
|
record.caller = TableReaderCaller::kUserApproximateSize;
|
|
3127
|
-
record.is_cache_hit =
|
|
3134
|
+
record.is_cache_hit = true;
|
|
3128
3135
|
expected_records.push_back(record);
|
|
3129
3136
|
expected_records.push_back(record);
|
|
3130
3137
|
VerifyBlockAccessTrace(&c, expected_records);
|
|
@@ -3169,24 +3176,24 @@ TEST_P(BlockBasedTableTest, TracingIterator) {
|
|
|
3169
3176
|
BlockCacheTraceRecord record;
|
|
3170
3177
|
record.block_type = TraceType::kBlockTraceIndexBlock;
|
|
3171
3178
|
record.caller = TableReaderCaller::kPrefetch;
|
|
3172
|
-
record.is_cache_hit =
|
|
3173
|
-
record.no_insert =
|
|
3179
|
+
record.is_cache_hit = false;
|
|
3180
|
+
record.no_insert = false;
|
|
3174
3181
|
expected_records.push_back(record);
|
|
3175
3182
|
record.block_type = TraceType::kBlockTraceFilterBlock;
|
|
3176
3183
|
expected_records.push_back(record);
|
|
3177
3184
|
// Then we should have three records for index and two data block access.
|
|
3178
3185
|
record.block_type = TraceType::kBlockTraceIndexBlock;
|
|
3179
3186
|
record.caller = TableReaderCaller::kUserIterator;
|
|
3180
|
-
record.is_cache_hit =
|
|
3187
|
+
record.is_cache_hit = true;
|
|
3181
3188
|
expected_records.push_back(record);
|
|
3182
3189
|
record.block_type = TraceType::kBlockTraceDataBlock;
|
|
3183
|
-
record.is_cache_hit =
|
|
3190
|
+
record.is_cache_hit = false;
|
|
3184
3191
|
expected_records.push_back(record);
|
|
3185
3192
|
expected_records.push_back(record);
|
|
3186
3193
|
// When we iterate this file for the second time, we should observe all cache
|
|
3187
3194
|
// hits.
|
|
3188
3195
|
record.block_type = TraceType::kBlockTraceIndexBlock;
|
|
3189
|
-
record.is_cache_hit =
|
|
3196
|
+
record.is_cache_hit = true;
|
|
3190
3197
|
expected_records.push_back(record);
|
|
3191
3198
|
record.block_type = TraceType::kBlockTraceDataBlock;
|
|
3192
3199
|
expected_records.push_back(record);
|
|
@@ -1568,7 +1568,7 @@ Status BlockCacheTraceAnalyzer::Analyze() {
|
|
|
1568
1568
|
trace_end_timestamp_in_seconds_ = access.access_timestamp / kMicrosInSecond;
|
|
1569
1569
|
miss_ratio_stats_.UpdateMetrics(access.access_timestamp,
|
|
1570
1570
|
is_user_access(access.caller),
|
|
1571
|
-
access.is_cache_hit
|
|
1571
|
+
!access.is_cache_hit);
|
|
1572
1572
|
if (cache_simulator_) {
|
|
1573
1573
|
cache_simulator_->Access(access);
|
|
1574
1574
|
}
|
|
@@ -95,7 +95,7 @@ struct BlockAccessInfo {
|
|
|
95
95
|
if (BlockCacheTraceHelper::IsGetOrMultiGetOnDataBlock(access.block_type,
|
|
96
96
|
access.caller)) {
|
|
97
97
|
num_keys = access.num_keys_in_block;
|
|
98
|
-
if (access.referenced_key_exist_in_block
|
|
98
|
+
if (access.referenced_key_exist_in_block) {
|
|
99
99
|
if (key_num_access_map.find(access.referenced_key) ==
|
|
100
100
|
key_num_access_map.end()) {
|
|
101
101
|
referenced_data_size += access.referenced_data_size;
|
|
@@ -114,14 +114,14 @@ class BlockCacheTracerTest : public testing::Test {
|
|
|
114
114
|
} else {
|
|
115
115
|
record.sst_fd_number = kSSTStoringOddKeys;
|
|
116
116
|
}
|
|
117
|
-
record.is_cache_hit =
|
|
118
|
-
record.no_insert =
|
|
117
|
+
record.is_cache_hit = false;
|
|
118
|
+
record.no_insert = false;
|
|
119
119
|
// Provide these fields for all block types.
|
|
120
120
|
// The writer should only write these fields for data blocks and the
|
|
121
121
|
// caller is either GET or MGET.
|
|
122
122
|
record.referenced_key =
|
|
123
123
|
kRefKeyPrefix + std::to_string(key_id) + std::string(8, 0);
|
|
124
|
-
record.referenced_key_exist_in_block =
|
|
124
|
+
record.referenced_key_exist_in_block = true;
|
|
125
125
|
record.num_keys_in_block = kNumKeysInBlock;
|
|
126
126
|
ASSERT_OK(writer->WriteBlockAccess(
|
|
127
127
|
record, record.block_key, record.cf_name, record.referenced_key));
|
|
@@ -223,15 +223,18 @@ class BlockCacheTracerTest : public testing::Test {
|
|
|
223
223
|
TEST_F(BlockCacheTracerTest, BlockCacheAnalyzer) {
|
|
224
224
|
{
|
|
225
225
|
// Generate a trace file.
|
|
226
|
-
|
|
226
|
+
BlockCacheTraceWriterOptions trace_writer_opt;
|
|
227
227
|
std::unique_ptr<TraceWriter> trace_writer;
|
|
228
228
|
ASSERT_OK(NewFileTraceWriter(env_, env_options_, trace_file_path_,
|
|
229
229
|
&trace_writer));
|
|
230
230
|
const auto& clock = env_->GetSystemClock();
|
|
231
|
-
BlockCacheTraceWriter
|
|
231
|
+
std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
|
|
232
|
+
NewBlockCacheTraceWriter(clock.get(), trace_writer_opt,
|
|
232
233
|
std::move(trace_writer));
|
|
233
|
-
|
|
234
|
-
|
|
234
|
+
ASSERT_NE(block_cache_trace_writer, nullptr);
|
|
235
|
+
ASSERT_OK(block_cache_trace_writer->WriteHeader());
|
|
236
|
+
WriteBlockAccess(block_cache_trace_writer.get(), 0,
|
|
237
|
+
TraceType::kBlockTraceDataBlock, 50);
|
|
235
238
|
ASSERT_OK(env_->FileExists(trace_file_path_));
|
|
236
239
|
}
|
|
237
240
|
{
|
|
@@ -612,21 +615,27 @@ TEST_F(BlockCacheTracerTest, MixedBlocks) {
|
|
|
612
615
|
// It contains two SST files with 25 blocks of odd numbered block_key in
|
|
613
616
|
// kSSTStoringOddKeys and 25 blocks of even numbered blocks_key in
|
|
614
617
|
// kSSTStoringEvenKeys.
|
|
615
|
-
|
|
618
|
+
BlockCacheTraceWriterOptions trace_writer_opt;
|
|
616
619
|
std::unique_ptr<TraceWriter> trace_writer;
|
|
617
620
|
const auto& clock = env_->GetSystemClock();
|
|
618
621
|
ASSERT_OK(NewFileTraceWriter(env_, env_options_, trace_file_path_,
|
|
619
622
|
&trace_writer));
|
|
620
|
-
BlockCacheTraceWriter
|
|
623
|
+
std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
|
|
624
|
+
NewBlockCacheTraceWriter(clock.get(), trace_writer_opt,
|
|
621
625
|
std::move(trace_writer));
|
|
622
|
-
|
|
626
|
+
ASSERT_NE(block_cache_trace_writer, nullptr);
|
|
627
|
+
ASSERT_OK(block_cache_trace_writer->WriteHeader());
|
|
623
628
|
// Write blocks of different types.
|
|
624
|
-
WriteBlockAccess(
|
|
625
|
-
10);
|
|
626
|
-
WriteBlockAccess(
|
|
627
|
-
|
|
628
|
-
WriteBlockAccess(
|
|
629
|
-
|
|
629
|
+
WriteBlockAccess(block_cache_trace_writer.get(), 0,
|
|
630
|
+
TraceType::kBlockTraceUncompressionDictBlock, 10);
|
|
631
|
+
WriteBlockAccess(block_cache_trace_writer.get(), 10,
|
|
632
|
+
TraceType::kBlockTraceDataBlock, 10);
|
|
633
|
+
WriteBlockAccess(block_cache_trace_writer.get(), 20,
|
|
634
|
+
TraceType::kBlockTraceFilterBlock, 10);
|
|
635
|
+
WriteBlockAccess(block_cache_trace_writer.get(), 30,
|
|
636
|
+
TraceType::kBlockTraceIndexBlock, 10);
|
|
637
|
+
WriteBlockAccess(block_cache_trace_writer.get(), 40,
|
|
638
|
+
TraceType::kBlockTraceRangeDeletionBlock, 10);
|
|
630
639
|
ASSERT_OK(env_->FileExists(trace_file_path_));
|
|
631
640
|
}
|
|
632
641
|
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
namespace ROCKSDB_NAMESPACE {
|
|
21
21
|
|
|
22
22
|
namespace {
|
|
23
|
-
bool ShouldTrace(const Slice& block_key,
|
|
23
|
+
bool ShouldTrace(const Slice& block_key,
|
|
24
|
+
const BlockCacheTraceOptions& trace_options) {
|
|
24
25
|
if (trace_options.sampling_frequency == 0 ||
|
|
25
26
|
trace_options.sampling_frequency == 1) {
|
|
26
27
|
return true;
|
|
@@ -36,6 +37,7 @@ const uint64_t kSecondInMinute = 60;
|
|
|
36
37
|
const uint64_t kSecondInHour = 3600;
|
|
37
38
|
const std::string BlockCacheTraceHelper::kUnknownColumnFamilyName =
|
|
38
39
|
"UnknownColumnFamily";
|
|
40
|
+
const uint64_t BlockCacheTraceRecord::kReservedGetId = 0;
|
|
39
41
|
const uint64_t BlockCacheTraceHelper::kReservedGetId = 0;
|
|
40
42
|
|
|
41
43
|
bool BlockCacheTraceHelper::IsGetOrMultiGetOnDataBlock(
|
|
@@ -79,9 +81,9 @@ uint64_t BlockCacheTraceHelper::GetSequenceNumber(
|
|
|
79
81
|
if (!IsGetOrMultiGet(access.caller)) {
|
|
80
82
|
return 0;
|
|
81
83
|
}
|
|
82
|
-
return access.get_from_user_specified_snapshot
|
|
83
|
-
?
|
|
84
|
-
:
|
|
84
|
+
return access.get_from_user_specified_snapshot
|
|
85
|
+
? 1 + GetInternalKeySeqno(access.referenced_key)
|
|
86
|
+
: 0;
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
uint64_t BlockCacheTraceHelper::GetBlockOffsetInFile(
|
|
@@ -99,14 +101,14 @@ uint64_t BlockCacheTraceHelper::GetBlockOffsetInFile(
|
|
|
99
101
|
return offset;
|
|
100
102
|
}
|
|
101
103
|
|
|
102
|
-
|
|
103
|
-
SystemClock* clock, const
|
|
104
|
+
BlockCacheTraceWriterImpl::BlockCacheTraceWriterImpl(
|
|
105
|
+
SystemClock* clock, const BlockCacheTraceWriterOptions& trace_options,
|
|
104
106
|
std::unique_ptr<TraceWriter>&& trace_writer)
|
|
105
107
|
: clock_(clock),
|
|
106
108
|
trace_options_(trace_options),
|
|
107
109
|
trace_writer_(std::move(trace_writer)) {}
|
|
108
110
|
|
|
109
|
-
Status
|
|
111
|
+
Status BlockCacheTraceWriterImpl::WriteBlockAccess(
|
|
110
112
|
const BlockCacheTraceRecord& record, const Slice& block_key,
|
|
111
113
|
const Slice& cf_name, const Slice& referenced_key) {
|
|
112
114
|
uint64_t trace_file_size = trace_writer_->GetFileSize();
|
|
@@ -141,7 +143,7 @@ Status BlockCacheTraceWriter::WriteBlockAccess(
|
|
|
141
143
|
return trace_writer_->Write(encoded_trace);
|
|
142
144
|
}
|
|
143
145
|
|
|
144
|
-
Status
|
|
146
|
+
Status BlockCacheTraceWriterImpl::WriteHeader() {
|
|
145
147
|
Trace trace;
|
|
146
148
|
trace.ts = clock_->NowMicros();
|
|
147
149
|
trace.type = TraceType::kTraceBegin;
|
|
@@ -255,13 +257,13 @@ Status BlockCacheTraceReader::ReadAccess(BlockCacheTraceRecord* record) {
|
|
|
255
257
|
return Status::Incomplete(
|
|
256
258
|
"Incomplete access record: Failed to read is_cache_hit.");
|
|
257
259
|
}
|
|
258
|
-
record->is_cache_hit = static_cast<
|
|
260
|
+
record->is_cache_hit = static_cast<char>(enc_slice[0]);
|
|
259
261
|
enc_slice.remove_prefix(kCharSize);
|
|
260
262
|
if (enc_slice.empty()) {
|
|
261
263
|
return Status::Incomplete(
|
|
262
264
|
"Incomplete access record: Failed to read no_insert.");
|
|
263
265
|
}
|
|
264
|
-
record->no_insert = static_cast<
|
|
266
|
+
record->no_insert = static_cast<char>(enc_slice[0]);
|
|
265
267
|
enc_slice.remove_prefix(kCharSize);
|
|
266
268
|
if (BlockCacheTraceHelper::IsGetOrMultiGet(record->caller)) {
|
|
267
269
|
if (!GetFixed64(&enc_slice, &record->get_id)) {
|
|
@@ -273,8 +275,7 @@ Status BlockCacheTraceReader::ReadAccess(BlockCacheTraceRecord* record) {
|
|
|
273
275
|
"Incomplete access record: Failed to read "
|
|
274
276
|
"get_from_user_specified_snapshot.");
|
|
275
277
|
}
|
|
276
|
-
record->get_from_user_specified_snapshot =
|
|
277
|
-
static_cast<Boolean>(enc_slice[0]);
|
|
278
|
+
record->get_from_user_specified_snapshot = static_cast<char>(enc_slice[0]);
|
|
278
279
|
enc_slice.remove_prefix(kCharSize);
|
|
279
280
|
Slice referenced_key;
|
|
280
281
|
if (!GetLengthPrefixedSlice(&enc_slice, &referenced_key)) {
|
|
@@ -299,7 +300,7 @@ Status BlockCacheTraceReader::ReadAccess(BlockCacheTraceRecord* record) {
|
|
|
299
300
|
"Incomplete access record: Failed to read "
|
|
300
301
|
"referenced_key_exist_in_block.");
|
|
301
302
|
}
|
|
302
|
-
record->referenced_key_exist_in_block = static_cast<
|
|
303
|
+
record->referenced_key_exist_in_block = static_cast<char>(enc_slice[0]);
|
|
303
304
|
}
|
|
304
305
|
return Status::OK();
|
|
305
306
|
}
|
|
@@ -391,14 +392,14 @@ Status BlockCacheHumanReadableTraceReader::ReadAccess(
|
|
|
391
392
|
record->level = static_cast<uint32_t>(ParseUint64(record_strs[6]));
|
|
392
393
|
record->sst_fd_number = ParseUint64(record_strs[7]);
|
|
393
394
|
record->caller = static_cast<TableReaderCaller>(ParseUint64(record_strs[8]));
|
|
394
|
-
record->no_insert = static_cast<
|
|
395
|
+
record->no_insert = static_cast<char>(ParseUint64(record_strs[9]));
|
|
395
396
|
record->get_id = ParseUint64(record_strs[10]);
|
|
396
397
|
uint64_t get_key_id = ParseUint64(record_strs[11]);
|
|
397
398
|
|
|
398
399
|
record->referenced_data_size = ParseUint64(record_strs[12]);
|
|
399
|
-
record->is_cache_hit = static_cast<
|
|
400
|
+
record->is_cache_hit = static_cast<char>(ParseUint64(record_strs[13]));
|
|
400
401
|
record->referenced_key_exist_in_block =
|
|
401
|
-
static_cast<
|
|
402
|
+
static_cast<char>(ParseUint64(record_strs[14]));
|
|
402
403
|
record->num_keys_in_block = ParseUint64(record_strs[15]);
|
|
403
404
|
uint64_t table_id = ParseUint64(record_strs[16]);
|
|
404
405
|
if (table_id > 0) {
|
|
@@ -408,7 +409,7 @@ Status BlockCacheHumanReadableTraceReader::ReadAccess(
|
|
|
408
409
|
}
|
|
409
410
|
uint64_t get_sequence_number = ParseUint64(record_strs[17]);
|
|
410
411
|
if (get_sequence_number > 0) {
|
|
411
|
-
record->get_from_user_specified_snapshot =
|
|
412
|
+
record->get_from_user_specified_snapshot = true;
|
|
412
413
|
// Decrement since valid seq number in the trace file equals traced seq
|
|
413
414
|
// number + 1.
|
|
414
415
|
get_sequence_number -= 1;
|
|
@@ -445,16 +446,15 @@ BlockCacheTracer::BlockCacheTracer() { writer_.store(nullptr); }
|
|
|
445
446
|
BlockCacheTracer::~BlockCacheTracer() { EndTrace(); }
|
|
446
447
|
|
|
447
448
|
Status BlockCacheTracer::StartTrace(
|
|
448
|
-
|
|
449
|
-
std::unique_ptr<
|
|
449
|
+
const BlockCacheTraceOptions& trace_options,
|
|
450
|
+
std::unique_ptr<BlockCacheTraceWriter>&& trace_writer) {
|
|
450
451
|
InstrumentedMutexLock lock_guard(&trace_writer_mutex_);
|
|
451
452
|
if (writer_.load()) {
|
|
452
453
|
return Status::Busy();
|
|
453
454
|
}
|
|
454
455
|
get_id_counter_.store(1);
|
|
455
456
|
trace_options_ = trace_options;
|
|
456
|
-
writer_.store(
|
|
457
|
-
new BlockCacheTraceWriter(clock, trace_options, std::move(trace_writer)));
|
|
457
|
+
writer_.store(trace_writer.release());
|
|
458
458
|
return writer_.load()->WriteHeader();
|
|
459
459
|
}
|
|
460
460
|
|
|
@@ -494,4 +494,11 @@ uint64_t BlockCacheTracer::NextGetId() {
|
|
|
494
494
|
return prev_value;
|
|
495
495
|
}
|
|
496
496
|
|
|
497
|
+
std::unique_ptr<BlockCacheTraceWriter> NewBlockCacheTraceWriter(
|
|
498
|
+
SystemClock* clock, const BlockCacheTraceWriterOptions& trace_options,
|
|
499
|
+
std::unique_ptr<TraceWriter>&& trace_writer) {
|
|
500
|
+
return std::unique_ptr<BlockCacheTraceWriter>(new BlockCacheTraceWriterImpl(
|
|
501
|
+
clock, trace_options, std::move(trace_writer)));
|
|
502
|
+
}
|
|
503
|
+
|
|
497
504
|
} // namespace ROCKSDB_NAMESPACE
|
|
@@ -9,9 +9,10 @@
|
|
|
9
9
|
#include <fstream>
|
|
10
10
|
|
|
11
11
|
#include "monitoring/instrumented_mutex.h"
|
|
12
|
+
#include "rocksdb/block_cache_trace_writer.h"
|
|
12
13
|
#include "rocksdb/options.h"
|
|
14
|
+
#include "rocksdb/table_reader_caller.h"
|
|
13
15
|
#include "rocksdb/trace_reader_writer.h"
|
|
14
|
-
#include "table/table_reader_caller.h"
|
|
15
16
|
#include "trace_replay/trace_replay.h"
|
|
16
17
|
|
|
17
18
|
namespace ROCKSDB_NAMESPACE {
|
|
@@ -102,65 +103,6 @@ struct BlockCacheLookupContext {
|
|
|
102
103
|
}
|
|
103
104
|
};
|
|
104
105
|
|
|
105
|
-
enum Boolean : char { kTrue = 1, kFalse = 0 };
|
|
106
|
-
|
|
107
|
-
struct BlockCacheTraceRecord {
|
|
108
|
-
// Required fields for all accesses.
|
|
109
|
-
uint64_t access_timestamp = 0;
|
|
110
|
-
std::string block_key;
|
|
111
|
-
TraceType block_type = TraceType::kTraceMax;
|
|
112
|
-
uint64_t block_size = 0;
|
|
113
|
-
uint64_t cf_id = 0;
|
|
114
|
-
std::string cf_name;
|
|
115
|
-
uint32_t level = 0;
|
|
116
|
-
uint64_t sst_fd_number = 0;
|
|
117
|
-
TableReaderCaller caller = TableReaderCaller::kMaxBlockCacheLookupCaller;
|
|
118
|
-
Boolean is_cache_hit = Boolean::kFalse;
|
|
119
|
-
Boolean no_insert = Boolean::kFalse;
|
|
120
|
-
// Required field for Get and MultiGet
|
|
121
|
-
uint64_t get_id = BlockCacheTraceHelper::kReservedGetId;
|
|
122
|
-
Boolean get_from_user_specified_snapshot = Boolean::kFalse;
|
|
123
|
-
std::string referenced_key;
|
|
124
|
-
// Required fields for data block and user Get/Multi-Get only.
|
|
125
|
-
uint64_t referenced_data_size = 0;
|
|
126
|
-
uint64_t num_keys_in_block = 0;
|
|
127
|
-
Boolean referenced_key_exist_in_block = Boolean::kFalse;
|
|
128
|
-
|
|
129
|
-
BlockCacheTraceRecord() {}
|
|
130
|
-
|
|
131
|
-
BlockCacheTraceRecord(
|
|
132
|
-
uint64_t _access_timestamp, std::string _block_key, TraceType _block_type,
|
|
133
|
-
uint64_t _block_size, uint64_t _cf_id, std::string _cf_name,
|
|
134
|
-
uint32_t _level, uint64_t _sst_fd_number, TableReaderCaller _caller,
|
|
135
|
-
bool _is_cache_hit, bool _no_insert,
|
|
136
|
-
uint64_t _get_id = BlockCacheTraceHelper::kReservedGetId,
|
|
137
|
-
bool _get_from_user_specified_snapshot = false,
|
|
138
|
-
std::string _referenced_key = "", uint64_t _referenced_data_size = 0,
|
|
139
|
-
uint64_t _num_keys_in_block = 0,
|
|
140
|
-
bool _referenced_key_exist_in_block = false)
|
|
141
|
-
: access_timestamp(_access_timestamp),
|
|
142
|
-
block_key(_block_key),
|
|
143
|
-
block_type(_block_type),
|
|
144
|
-
block_size(_block_size),
|
|
145
|
-
cf_id(_cf_id),
|
|
146
|
-
cf_name(_cf_name),
|
|
147
|
-
level(_level),
|
|
148
|
-
sst_fd_number(_sst_fd_number),
|
|
149
|
-
caller(_caller),
|
|
150
|
-
is_cache_hit(_is_cache_hit ? Boolean::kTrue : Boolean::kFalse),
|
|
151
|
-
no_insert(_no_insert ? Boolean::kTrue : Boolean::kFalse),
|
|
152
|
-
get_id(_get_id),
|
|
153
|
-
get_from_user_specified_snapshot(_get_from_user_specified_snapshot
|
|
154
|
-
? Boolean::kTrue
|
|
155
|
-
: Boolean::kFalse),
|
|
156
|
-
referenced_key(_referenced_key),
|
|
157
|
-
referenced_data_size(_referenced_data_size),
|
|
158
|
-
num_keys_in_block(_num_keys_in_block),
|
|
159
|
-
referenced_key_exist_in_block(
|
|
160
|
-
_referenced_key_exist_in_block ? Boolean::kTrue : Boolean::kFalse) {
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
|
|
164
106
|
struct BlockCacheTraceHeader {
|
|
165
107
|
uint64_t start_time;
|
|
166
108
|
uint32_t rocksdb_major_version;
|
|
@@ -171,16 +113,18 @@ struct BlockCacheTraceHeader {
|
|
|
171
113
|
// user-provided TraceWriter. Every RocksDB operation is written as a single
|
|
172
114
|
// trace. Each trace will have a timestamp and type, followed by the trace
|
|
173
115
|
// payload.
|
|
174
|
-
class BlockCacheTraceWriter {
|
|
116
|
+
class BlockCacheTraceWriterImpl : public BlockCacheTraceWriter {
|
|
175
117
|
public:
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
118
|
+
BlockCacheTraceWriterImpl(SystemClock* clock,
|
|
119
|
+
const BlockCacheTraceWriterOptions& trace_options,
|
|
120
|
+
std::unique_ptr<TraceWriter>&& trace_writer);
|
|
121
|
+
~BlockCacheTraceWriterImpl() = default;
|
|
179
122
|
// No copy and move.
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
123
|
+
BlockCacheTraceWriterImpl(const BlockCacheTraceWriterImpl&) = delete;
|
|
124
|
+
BlockCacheTraceWriterImpl& operator=(const BlockCacheTraceWriterImpl&) =
|
|
125
|
+
delete;
|
|
126
|
+
BlockCacheTraceWriterImpl(BlockCacheTraceWriterImpl&&) = delete;
|
|
127
|
+
BlockCacheTraceWriterImpl& operator=(BlockCacheTraceWriterImpl&&) = delete;
|
|
184
128
|
|
|
185
129
|
// Pass Slice references to avoid copy.
|
|
186
130
|
Status WriteBlockAccess(const BlockCacheTraceRecord& record,
|
|
@@ -193,7 +137,7 @@ class BlockCacheTraceWriter {
|
|
|
193
137
|
|
|
194
138
|
private:
|
|
195
139
|
SystemClock* clock_;
|
|
196
|
-
|
|
140
|
+
BlockCacheTraceWriterOptions trace_options_;
|
|
197
141
|
std::unique_ptr<TraceWriter> trace_writer_;
|
|
198
142
|
};
|
|
199
143
|
|
|
@@ -267,8 +211,8 @@ class BlockCacheTracer {
|
|
|
267
211
|
BlockCacheTracer& operator=(BlockCacheTracer&&) = delete;
|
|
268
212
|
|
|
269
213
|
// Start writing block cache accesses to the trace_writer.
|
|
270
|
-
Status StartTrace(
|
|
271
|
-
std::unique_ptr<
|
|
214
|
+
Status StartTrace(const BlockCacheTraceOptions& trace_options,
|
|
215
|
+
std::unique_ptr<BlockCacheTraceWriter>&& trace_writer);
|
|
272
216
|
|
|
273
217
|
// Stop writing block cache accesses to the trace_writer.
|
|
274
218
|
void EndTrace();
|
|
@@ -285,7 +229,7 @@ class BlockCacheTracer {
|
|
|
285
229
|
uint64_t NextGetId();
|
|
286
230
|
|
|
287
231
|
private:
|
|
288
|
-
|
|
232
|
+
BlockCacheTraceOptions trace_options_;
|
|
289
233
|
// A mutex protects the writer_.
|
|
290
234
|
InstrumentedMutex trace_writer_mutex_;
|
|
291
235
|
std::atomic<BlockCacheTraceWriter*> writer_;
|
|
@@ -74,17 +74,17 @@ class BlockCacheTracerTest : public testing::Test {
|
|
|
74
74
|
record.caller = GetCaller(key_id);
|
|
75
75
|
record.level = kLevel;
|
|
76
76
|
record.sst_fd_number = kSSTFDNumber + key_id;
|
|
77
|
-
record.is_cache_hit =
|
|
78
|
-
record.no_insert =
|
|
77
|
+
record.is_cache_hit = false;
|
|
78
|
+
record.no_insert = false;
|
|
79
79
|
// Provide get_id for all callers. The writer should only write get_id
|
|
80
80
|
// when the caller is either GET or MGET.
|
|
81
81
|
record.get_id = key_id + 1;
|
|
82
|
-
record.get_from_user_specified_snapshot =
|
|
82
|
+
record.get_from_user_specified_snapshot = true;
|
|
83
83
|
// Provide these fields for all block types.
|
|
84
84
|
// The writer should only write these fields for data blocks and the
|
|
85
85
|
// caller is either GET or MGET.
|
|
86
86
|
record.referenced_key = (kRefKeyPrefix + std::to_string(key_id));
|
|
87
|
-
record.referenced_key_exist_in_block =
|
|
87
|
+
record.referenced_key_exist_in_block = true;
|
|
88
88
|
record.num_keys_in_block = kNumKeysInBlock;
|
|
89
89
|
record.referenced_data_size = kReferencedDataSize + key_id;
|
|
90
90
|
ASSERT_OK(writer->WriteBlockAccess(
|
|
@@ -104,10 +104,10 @@ class BlockCacheTracerTest : public testing::Test {
|
|
|
104
104
|
record.caller = GetCaller(key_id);
|
|
105
105
|
record.level = kLevel;
|
|
106
106
|
record.sst_fd_number = kSSTFDNumber + key_id;
|
|
107
|
-
record.is_cache_hit =
|
|
108
|
-
record.no_insert =
|
|
107
|
+
record.is_cache_hit = false;
|
|
108
|
+
record.no_insert = false;
|
|
109
109
|
record.referenced_key = kRefKeyPrefix + std::to_string(key_id);
|
|
110
|
-
record.referenced_key_exist_in_block =
|
|
110
|
+
record.referenced_key_exist_in_block = true;
|
|
111
111
|
record.num_keys_in_block = kNumKeysInBlock;
|
|
112
112
|
return record;
|
|
113
113
|
}
|
|
@@ -127,28 +127,28 @@ class BlockCacheTracerTest : public testing::Test {
|
|
|
127
127
|
ASSERT_EQ(GetCaller(key_id), record.caller);
|
|
128
128
|
ASSERT_EQ(kLevel, record.level);
|
|
129
129
|
ASSERT_EQ(kSSTFDNumber + key_id, record.sst_fd_number);
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
ASSERT_FALSE(record.is_cache_hit);
|
|
131
|
+
ASSERT_FALSE(record.no_insert);
|
|
132
132
|
if (record.caller == TableReaderCaller::kUserGet ||
|
|
133
133
|
record.caller == TableReaderCaller::kUserMultiGet) {
|
|
134
134
|
ASSERT_EQ(key_id + 1, record.get_id);
|
|
135
|
-
|
|
135
|
+
ASSERT_TRUE(record.get_from_user_specified_snapshot);
|
|
136
136
|
ASSERT_EQ(kRefKeyPrefix + std::to_string(key_id),
|
|
137
137
|
record.referenced_key);
|
|
138
138
|
} else {
|
|
139
139
|
ASSERT_EQ(BlockCacheTraceHelper::kReservedGetId, record.get_id);
|
|
140
|
-
|
|
140
|
+
ASSERT_FALSE(record.get_from_user_specified_snapshot);
|
|
141
141
|
ASSERT_EQ("", record.referenced_key);
|
|
142
142
|
}
|
|
143
143
|
if (block_type == TraceType::kBlockTraceDataBlock &&
|
|
144
144
|
(record.caller == TableReaderCaller::kUserGet ||
|
|
145
145
|
record.caller == TableReaderCaller::kUserMultiGet)) {
|
|
146
|
-
|
|
146
|
+
ASSERT_TRUE(record.referenced_key_exist_in_block);
|
|
147
147
|
ASSERT_EQ(kNumKeysInBlock, record.num_keys_in_block);
|
|
148
148
|
ASSERT_EQ(kReferencedDataSize + key_id, record.referenced_data_size);
|
|
149
149
|
continue;
|
|
150
150
|
}
|
|
151
|
-
|
|
151
|
+
ASSERT_FALSE(record.referenced_key_exist_in_block);
|
|
152
152
|
ASSERT_EQ(0, record.num_keys_in_block);
|
|
153
153
|
ASSERT_EQ(0, record.referenced_data_size);
|
|
154
154
|
}
|
|
@@ -188,12 +188,18 @@ TEST_F(BlockCacheTracerTest, AtomicWriteBeforeStartTrace) {
|
|
|
188
188
|
TEST_F(BlockCacheTracerTest, AtomicWrite) {
|
|
189
189
|
BlockCacheTraceRecord record = GenerateAccessRecord();
|
|
190
190
|
{
|
|
191
|
-
|
|
191
|
+
BlockCacheTraceWriterOptions trace_writer_opt;
|
|
192
|
+
BlockCacheTraceOptions trace_opt;
|
|
192
193
|
std::unique_ptr<TraceWriter> trace_writer;
|
|
193
194
|
ASSERT_OK(NewFileTraceWriter(env_, env_options_, trace_file_path_,
|
|
194
195
|
&trace_writer));
|
|
196
|
+
std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
|
|
197
|
+
NewBlockCacheTraceWriter(env_->GetSystemClock().get(), trace_writer_opt,
|
|
198
|
+
std::move(trace_writer));
|
|
199
|
+
ASSERT_NE(block_cache_trace_writer, nullptr);
|
|
195
200
|
BlockCacheTracer writer;
|
|
196
|
-
ASSERT_OK(
|
|
201
|
+
ASSERT_OK(
|
|
202
|
+
writer.StartTrace(trace_opt, std::move(block_cache_trace_writer)));
|
|
197
203
|
ASSERT_OK(writer.WriteBlockAccess(record, record.block_key, record.cf_name,
|
|
198
204
|
record.referenced_key));
|
|
199
205
|
ASSERT_OK(env_->FileExists(trace_file_path_));
|
|
@@ -214,25 +220,36 @@ TEST_F(BlockCacheTracerTest, AtomicWrite) {
|
|
|
214
220
|
}
|
|
215
221
|
|
|
216
222
|
TEST_F(BlockCacheTracerTest, ConsecutiveStartTrace) {
|
|
217
|
-
|
|
223
|
+
BlockCacheTraceWriterOptions trace_writer_opt;
|
|
224
|
+
BlockCacheTraceOptions trace_opt;
|
|
218
225
|
std::unique_ptr<TraceWriter> trace_writer;
|
|
219
226
|
ASSERT_OK(
|
|
220
227
|
NewFileTraceWriter(env_, env_options_, trace_file_path_, &trace_writer));
|
|
228
|
+
std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
|
|
229
|
+
NewBlockCacheTraceWriter(env_->GetSystemClock().get(), trace_writer_opt,
|
|
230
|
+
std::move(trace_writer));
|
|
231
|
+
ASSERT_NE(block_cache_trace_writer, nullptr);
|
|
221
232
|
BlockCacheTracer writer;
|
|
222
|
-
ASSERT_OK(writer.StartTrace(
|
|
223
|
-
ASSERT_NOK(writer.StartTrace(
|
|
233
|
+
ASSERT_OK(writer.StartTrace(trace_opt, std::move(block_cache_trace_writer)));
|
|
234
|
+
ASSERT_NOK(writer.StartTrace(trace_opt, std::move(block_cache_trace_writer)));
|
|
224
235
|
ASSERT_OK(env_->FileExists(trace_file_path_));
|
|
225
236
|
}
|
|
226
237
|
|
|
227
238
|
TEST_F(BlockCacheTracerTest, AtomicNoWriteAfterEndTrace) {
|
|
228
239
|
BlockCacheTraceRecord record = GenerateAccessRecord();
|
|
229
240
|
{
|
|
230
|
-
|
|
241
|
+
BlockCacheTraceWriterOptions trace_writer_opt;
|
|
242
|
+
BlockCacheTraceOptions trace_opt;
|
|
231
243
|
std::unique_ptr<TraceWriter> trace_writer;
|
|
232
244
|
ASSERT_OK(NewFileTraceWriter(env_, env_options_, trace_file_path_,
|
|
233
245
|
&trace_writer));
|
|
246
|
+
std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
|
|
247
|
+
NewBlockCacheTraceWriter(env_->GetSystemClock().get(), trace_writer_opt,
|
|
248
|
+
std::move(trace_writer));
|
|
249
|
+
ASSERT_NE(block_cache_trace_writer, nullptr);
|
|
234
250
|
BlockCacheTracer writer;
|
|
235
|
-
ASSERT_OK(
|
|
251
|
+
ASSERT_OK(
|
|
252
|
+
writer.StartTrace(trace_opt, std::move(block_cache_trace_writer)));
|
|
236
253
|
ASSERT_OK(writer.WriteBlockAccess(record, record.block_key, record.cf_name,
|
|
237
254
|
record.referenced_key));
|
|
238
255
|
writer.EndTrace();
|
|
@@ -260,14 +277,20 @@ TEST_F(BlockCacheTracerTest, AtomicNoWriteAfterEndTrace) {
|
|
|
260
277
|
TEST_F(BlockCacheTracerTest, NextGetId) {
|
|
261
278
|
BlockCacheTracer writer;
|
|
262
279
|
{
|
|
263
|
-
|
|
280
|
+
BlockCacheTraceWriterOptions trace_writer_opt;
|
|
281
|
+
BlockCacheTraceOptions trace_opt;
|
|
264
282
|
std::unique_ptr<TraceWriter> trace_writer;
|
|
265
283
|
ASSERT_OK(NewFileTraceWriter(env_, env_options_, trace_file_path_,
|
|
266
284
|
&trace_writer));
|
|
285
|
+
std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
|
|
286
|
+
NewBlockCacheTraceWriter(env_->GetSystemClock().get(), trace_writer_opt,
|
|
287
|
+
std::move(trace_writer));
|
|
288
|
+
ASSERT_NE(block_cache_trace_writer, nullptr);
|
|
267
289
|
// next get id should always return 0 before we call StartTrace.
|
|
268
290
|
ASSERT_EQ(0, writer.NextGetId());
|
|
269
291
|
ASSERT_EQ(0, writer.NextGetId());
|
|
270
|
-
ASSERT_OK(
|
|
292
|
+
ASSERT_OK(
|
|
293
|
+
writer.StartTrace(trace_opt, std::move(block_cache_trace_writer)));
|
|
271
294
|
ASSERT_EQ(1, writer.NextGetId());
|
|
272
295
|
ASSERT_EQ(2, writer.NextGetId());
|
|
273
296
|
writer.EndTrace();
|
|
@@ -277,11 +300,17 @@ TEST_F(BlockCacheTracerTest, NextGetId) {
|
|
|
277
300
|
|
|
278
301
|
// Start trace again and next get id should return 1.
|
|
279
302
|
{
|
|
280
|
-
|
|
303
|
+
BlockCacheTraceWriterOptions trace_writer_opt;
|
|
304
|
+
BlockCacheTraceOptions trace_opt;
|
|
281
305
|
std::unique_ptr<TraceWriter> trace_writer;
|
|
282
306
|
ASSERT_OK(NewFileTraceWriter(env_, env_options_, trace_file_path_,
|
|
283
307
|
&trace_writer));
|
|
284
|
-
|
|
308
|
+
std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
|
|
309
|
+
NewBlockCacheTraceWriter(env_->GetSystemClock().get(), trace_writer_opt,
|
|
310
|
+
std::move(trace_writer));
|
|
311
|
+
ASSERT_NE(block_cache_trace_writer, nullptr);
|
|
312
|
+
ASSERT_OK(
|
|
313
|
+
writer.StartTrace(trace_opt, std::move(block_cache_trace_writer)));
|
|
285
314
|
ASSERT_EQ(1, writer.NextGetId());
|
|
286
315
|
}
|
|
287
316
|
}
|
|
@@ -289,19 +318,26 @@ TEST_F(BlockCacheTracerTest, NextGetId) {
|
|
|
289
318
|
TEST_F(BlockCacheTracerTest, MixedBlocks) {
|
|
290
319
|
{
|
|
291
320
|
// Generate a trace file containing a mix of blocks.
|
|
292
|
-
|
|
321
|
+
BlockCacheTraceWriterOptions trace_writer_opt;
|
|
293
322
|
std::unique_ptr<TraceWriter> trace_writer;
|
|
294
323
|
ASSERT_OK(NewFileTraceWriter(env_, env_options_, trace_file_path_,
|
|
295
324
|
&trace_writer));
|
|
296
|
-
BlockCacheTraceWriter
|
|
297
|
-
|
|
325
|
+
std::unique_ptr<BlockCacheTraceWriter> block_cache_trace_writer =
|
|
326
|
+
NewBlockCacheTraceWriter(env_->GetSystemClock().get(), trace_writer_opt,
|
|
327
|
+
std::move(trace_writer));
|
|
328
|
+
ASSERT_NE(block_cache_trace_writer, nullptr);
|
|
329
|
+
ASSERT_OK(block_cache_trace_writer->WriteHeader());
|
|
298
330
|
// Write blocks of different types.
|
|
299
|
-
WriteBlockAccess(
|
|
300
|
-
10);
|
|
301
|
-
WriteBlockAccess(
|
|
302
|
-
|
|
303
|
-
WriteBlockAccess(
|
|
304
|
-
|
|
331
|
+
WriteBlockAccess(block_cache_trace_writer.get(), 0,
|
|
332
|
+
TraceType::kBlockTraceUncompressionDictBlock, 10);
|
|
333
|
+
WriteBlockAccess(block_cache_trace_writer.get(), 10,
|
|
334
|
+
TraceType::kBlockTraceDataBlock, 10);
|
|
335
|
+
WriteBlockAccess(block_cache_trace_writer.get(), 20,
|
|
336
|
+
TraceType::kBlockTraceFilterBlock, 10);
|
|
337
|
+
WriteBlockAccess(block_cache_trace_writer.get(), 30,
|
|
338
|
+
TraceType::kBlockTraceIndexBlock, 10);
|
|
339
|
+
WriteBlockAccess(block_cache_trace_writer.get(), 40,
|
|
340
|
+
TraceType::kBlockTraceRangeDeletionBlock, 10);
|
|
305
341
|
ASSERT_OK(env_->FileExists(trace_file_path_));
|
|
306
342
|
}
|
|
307
343
|
|
|
@@ -332,7 +368,7 @@ TEST_F(BlockCacheTracerTest, HumanReadableTrace) {
|
|
|
332
368
|
record.get_id = 1;
|
|
333
369
|
record.referenced_key = "";
|
|
334
370
|
record.caller = TableReaderCaller::kUserGet;
|
|
335
|
-
record.get_from_user_specified_snapshot =
|
|
371
|
+
record.get_from_user_specified_snapshot = true;
|
|
336
372
|
record.referenced_data_size = kReferencedDataSize;
|
|
337
373
|
PutFixed32(&record.referenced_key, 111);
|
|
338
374
|
PutLengthPrefixedSlice(&record.referenced_key, "get_key");
|
|
@@ -359,11 +395,11 @@ TEST_F(BlockCacheTracerTest, HumanReadableTrace) {
|
|
|
359
395
|
ASSERT_EQ(TableReaderCaller::kUserGet, read_record.caller);
|
|
360
396
|
ASSERT_EQ(kLevel, read_record.level);
|
|
361
397
|
ASSERT_EQ(kSSTFDNumber, read_record.sst_fd_number);
|
|
362
|
-
|
|
363
|
-
|
|
398
|
+
ASSERT_FALSE(read_record.is_cache_hit);
|
|
399
|
+
ASSERT_FALSE(read_record.no_insert);
|
|
364
400
|
ASSERT_EQ(1, read_record.get_id);
|
|
365
|
-
|
|
366
|
-
|
|
401
|
+
ASSERT_TRUE(read_record.get_from_user_specified_snapshot);
|
|
402
|
+
ASSERT_TRUE(read_record.referenced_key_exist_in_block);
|
|
367
403
|
ASSERT_EQ(kNumKeysInBlock, read_record.num_keys_in_block);
|
|
368
404
|
ASSERT_EQ(kReferencedDataSize, read_record.referenced_data_size);
|
|
369
405
|
ASSERT_EQ(record.block_key.size(), read_record.block_key.size());
|
|
@@ -15,65 +15,45 @@ namespace ROCKSDB_NAMESPACE {
|
|
|
15
15
|
|
|
16
16
|
// Wrapper of user comparator, with auto increment to
|
|
17
17
|
// perf_context.user_key_comparison_count.
|
|
18
|
-
class UserComparatorWrapper
|
|
18
|
+
class UserComparatorWrapper {
|
|
19
19
|
public:
|
|
20
20
|
// `UserComparatorWrapper`s constructed with the default constructor are not
|
|
21
21
|
// usable and will segfault on any attempt to use them for comparisons.
|
|
22
22
|
UserComparatorWrapper() : user_comparator_(nullptr) {}
|
|
23
23
|
|
|
24
24
|
explicit UserComparatorWrapper(const Comparator* const user_cmp)
|
|
25
|
-
:
|
|
25
|
+
: user_comparator_(user_cmp) {}
|
|
26
26
|
|
|
27
27
|
~UserComparatorWrapper() = default;
|
|
28
28
|
|
|
29
29
|
const Comparator* user_comparator() const { return user_comparator_; }
|
|
30
30
|
|
|
31
|
-
int Compare(const Slice& a, const Slice& b) const
|
|
31
|
+
int Compare(const Slice& a, const Slice& b) const {
|
|
32
32
|
PERF_COUNTER_ADD(user_key_comparison_count, 1);
|
|
33
33
|
return user_comparator_->Compare(a, b);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
bool Equal(const Slice& a, const Slice& b) const
|
|
36
|
+
bool Equal(const Slice& a, const Slice& b) const {
|
|
37
37
|
PERF_COUNTER_ADD(user_key_comparison_count, 1);
|
|
38
38
|
return user_comparator_->Equal(a, b);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
void FindShortestSeparator(std::string* start,
|
|
44
|
-
const Slice& limit) const override {
|
|
45
|
-
return user_comparator_->FindShortestSeparator(start, limit);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
void FindShortSuccessor(std::string* key) const override {
|
|
49
|
-
return user_comparator_->FindShortSuccessor(key);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const Comparator* GetRootComparator() const override {
|
|
53
|
-
return user_comparator_->GetRootComparator();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
bool IsSameLengthImmediateSuccessor(const Slice& s,
|
|
57
|
-
const Slice& t) const override {
|
|
58
|
-
return user_comparator_->IsSameLengthImmediateSuccessor(s, t);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
bool CanKeysWithDifferentByteContentsBeEqual() const override {
|
|
62
|
-
return user_comparator_->CanKeysWithDifferentByteContentsBeEqual();
|
|
41
|
+
int CompareTimestamp(const Slice& ts1, const Slice& ts2) const {
|
|
42
|
+
return user_comparator_->CompareTimestamp(ts1, ts2);
|
|
63
43
|
}
|
|
64
44
|
|
|
65
|
-
int
|
|
66
|
-
|
|
45
|
+
int CompareWithoutTimestamp(const Slice& a, const Slice& b) const {
|
|
46
|
+
PERF_COUNTER_ADD(user_key_comparison_count, 1);
|
|
47
|
+
return user_comparator_->CompareWithoutTimestamp(a, b);
|
|
67
48
|
}
|
|
68
49
|
|
|
69
|
-
using Comparator::CompareWithoutTimestamp;
|
|
70
50
|
int CompareWithoutTimestamp(const Slice& a, bool a_has_ts, const Slice& b,
|
|
71
|
-
bool b_has_ts) const
|
|
51
|
+
bool b_has_ts) const {
|
|
72
52
|
PERF_COUNTER_ADD(user_key_comparison_count, 1);
|
|
73
53
|
return user_comparator_->CompareWithoutTimestamp(a, a_has_ts, b, b_has_ts);
|
|
74
54
|
}
|
|
75
55
|
|
|
76
|
-
bool EqualWithoutTimestamp(const Slice& a, const Slice& b) const
|
|
56
|
+
bool EqualWithoutTimestamp(const Slice& a, const Slice& b) const {
|
|
77
57
|
return user_comparator_->EqualWithoutTimestamp(a, b);
|
|
78
58
|
}
|
|
79
59
|
|
|
@@ -41,7 +41,7 @@ void CacheSimulator::Access(const BlockCacheTraceRecord& access) {
|
|
|
41
41
|
const bool is_user_access =
|
|
42
42
|
BlockCacheTraceHelper::IsUserAccess(access.caller);
|
|
43
43
|
bool is_cache_miss = true;
|
|
44
|
-
if (ghost_cache_ && access.no_insert
|
|
44
|
+
if (ghost_cache_ && !access.no_insert) {
|
|
45
45
|
admit = ghost_cache_->Admit(access.block_key);
|
|
46
46
|
}
|
|
47
47
|
auto handle = sim_cache_->Lookup(access.block_key);
|
|
@@ -49,7 +49,7 @@ void CacheSimulator::Access(const BlockCacheTraceRecord& access) {
|
|
|
49
49
|
sim_cache_->Release(handle);
|
|
50
50
|
is_cache_miss = false;
|
|
51
51
|
} else {
|
|
52
|
-
if (access.no_insert
|
|
52
|
+
if (!access.no_insert && admit && access.block_size > 0) {
|
|
53
53
|
// Ignore errors on insert
|
|
54
54
|
auto s = sim_cache_->Insert(access.block_key, /*value=*/nullptr,
|
|
55
55
|
access.block_size,
|
|
@@ -43,11 +43,11 @@ class CacheSimulatorTest : public testing::Test {
|
|
|
43
43
|
record.level = 6;
|
|
44
44
|
record.sst_fd_number = 0;
|
|
45
45
|
record.get_id = getid;
|
|
46
|
-
record.is_cache_hit =
|
|
47
|
-
record.no_insert =
|
|
46
|
+
record.is_cache_hit = false;
|
|
47
|
+
record.no_insert = false;
|
|
48
48
|
record.referenced_key =
|
|
49
49
|
kRefKeyPrefix + std::to_string(kGetId) + kRefKeySequenceNumber;
|
|
50
|
-
record.referenced_key_exist_in_block =
|
|
50
|
+
record.referenced_key_exist_in_block = true;
|
|
51
51
|
record.referenced_data_size = 100;
|
|
52
52
|
record.num_keys_in_block = 300;
|
|
53
53
|
return record;
|
|
@@ -64,8 +64,8 @@ class CacheSimulatorTest : public testing::Test {
|
|
|
64
64
|
record.caller = TableReaderCaller::kCompaction;
|
|
65
65
|
record.level = 6;
|
|
66
66
|
record.sst_fd_number = kCompactionBlockId;
|
|
67
|
-
record.is_cache_hit =
|
|
68
|
-
record.no_insert =
|
|
67
|
+
record.is_cache_hit = false;
|
|
68
|
+
record.no_insert = true;
|
|
69
69
|
return record;
|
|
70
70
|
}
|
|
71
71
|
|
|
@@ -200,17 +200,17 @@ TEST_F(CacheSimulatorTest, GhostPrioritizedCacheSimulator) {
|
|
|
200
200
|
TEST_F(CacheSimulatorTest, HybridRowBlockCacheSimulator) {
|
|
201
201
|
uint64_t block_id = 100;
|
|
202
202
|
BlockCacheTraceRecord first_get = GenerateGetRecord(kGetId);
|
|
203
|
-
first_get.get_from_user_specified_snapshot =
|
|
203
|
+
first_get.get_from_user_specified_snapshot = true;
|
|
204
204
|
BlockCacheTraceRecord second_get = GenerateGetRecord(kGetId + 1);
|
|
205
205
|
second_get.referenced_data_size = 0;
|
|
206
|
-
second_get.referenced_key_exist_in_block =
|
|
207
|
-
second_get.get_from_user_specified_snapshot =
|
|
206
|
+
second_get.referenced_key_exist_in_block = false;
|
|
207
|
+
second_get.get_from_user_specified_snapshot = true;
|
|
208
208
|
BlockCacheTraceRecord third_get = GenerateGetRecord(kGetId + 2);
|
|
209
209
|
third_get.referenced_data_size = 0;
|
|
210
|
-
third_get.referenced_key_exist_in_block =
|
|
210
|
+
third_get.referenced_key_exist_in_block = false;
|
|
211
211
|
third_get.referenced_key = kRefKeyPrefix + "third_get";
|
|
212
212
|
// We didn't find the referenced key in the third get.
|
|
213
|
-
third_get.referenced_key_exist_in_block =
|
|
213
|
+
third_get.referenced_key_exist_in_block = false;
|
|
214
214
|
third_get.referenced_data_size = 0;
|
|
215
215
|
std::shared_ptr<Cache> sim_cache =
|
|
216
216
|
NewLRUCache(/*capacity=*/kCacheSize, /*num_shard_bits=*/1,
|
|
@@ -308,12 +308,12 @@ TEST_F(CacheSimulatorTest, HybridRowBlockCacheSimulatorGetTest) {
|
|
|
308
308
|
get.access_timestamp = 0;
|
|
309
309
|
get.block_key = "1";
|
|
310
310
|
get.get_id = 1;
|
|
311
|
-
get.get_from_user_specified_snapshot =
|
|
311
|
+
get.get_from_user_specified_snapshot = false;
|
|
312
312
|
get.referenced_key =
|
|
313
313
|
kRefKeyPrefix + std::to_string(1) + kRefKeySequenceNumber;
|
|
314
|
-
get.no_insert =
|
|
314
|
+
get.no_insert = false;
|
|
315
315
|
get.sst_fd_number = 0;
|
|
316
|
-
get.get_from_user_specified_snapshot =
|
|
316
|
+
get.get_from_user_specified_snapshot = false;
|
|
317
317
|
|
|
318
318
|
LRUCacheOptions co;
|
|
319
319
|
co.capacity = 16;
|
package/deps/rocksdb/rocksdb.gyp
CHANGED
|
@@ -311,6 +311,7 @@
|
|
|
311
311
|
"rocksdb/options/options.cc",
|
|
312
312
|
"rocksdb/options/options_helper.cc",
|
|
313
313
|
"rocksdb/options/options_parser.cc",
|
|
314
|
+
"rocksdb/port/mmap.cc",
|
|
314
315
|
"rocksdb/port/stack_trace.cc",
|
|
315
316
|
"rocksdb/table/adaptive/adaptive_table_factory.cc",
|
|
316
317
|
"rocksdb/table/block_based/binary_search_index_reader.cc",
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|