@nxtedition/rocksdb 7.1.4 → 7.1.5
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/iostats.patch +19 -0
- package/deps/rocksdb/rocksdb/CMakeLists.txt +15 -1
- package/deps/rocksdb/rocksdb/cache/cache_test.cc +93 -58
- package/deps/rocksdb/rocksdb/cache/clock_cache.cc +88 -40
- package/deps/rocksdb/rocksdb/cache/clock_cache.h +57 -32
- package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache.cc +103 -28
- package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache.h +33 -1
- package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache_test.cc +177 -38
- package/deps/rocksdb/rocksdb/cache/fast_lru_cache.cc +3 -1
- package/deps/rocksdb/rocksdb/cache/lru_cache.cc +2 -2
- package/deps/rocksdb/rocksdb/cache/lru_cache_test.cc +125 -71
- package/deps/rocksdb/rocksdb/crash_test.mk +15 -1
- package/deps/rocksdb/rocksdb/db/arena_wrapped_db_iter.cc +2 -2
- package/deps/rocksdb/rocksdb/db/blob/blob_index.h +1 -1
- package/deps/rocksdb/rocksdb/db/blob/blob_log_format.cc +3 -5
- package/deps/rocksdb/rocksdb/db/blob/blob_log_writer.cc +25 -19
- package/deps/rocksdb/rocksdb/db/blob/db_blob_basic_test.cc +149 -0
- package/deps/rocksdb/rocksdb/db/blob/db_blob_compaction_test.cc +36 -0
- package/deps/rocksdb/rocksdb/db/column_family.cc +2 -15
- package/deps/rocksdb/rocksdb/db/column_family_test.cc +17 -4
- package/deps/rocksdb/rocksdb/db/compact_files_test.cc +8 -8
- package/deps/rocksdb/rocksdb/db/compaction/compaction.cc +0 -7
- package/deps/rocksdb/rocksdb/db/compaction/compaction.h +5 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.cc +50 -52
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.h +33 -11
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +41 -10
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job_test.cc +1 -2
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_test.cc +143 -2
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.cc +43 -18
- package/deps/rocksdb/rocksdb/db/compaction/tiered_compaction_test.cc +48 -65
- package/deps/rocksdb/rocksdb/db/corruption_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/db_basic_test.cc +73 -4
- package/deps/rocksdb/rocksdb/db/db_block_cache_test.cc +17 -8
- package/deps/rocksdb/rocksdb/db/db_compaction_test.cc +71 -2
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +144 -33
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +18 -35
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +11 -5
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_experimental.cc +7 -7
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +15 -8
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_readonly.cc +2 -1
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_secondary.cc +3 -1
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_write.cc +11 -0
- package/deps/rocksdb/rocksdb/db/db_iter.cc +69 -11
- package/deps/rocksdb/rocksdb/db/db_iter.h +16 -0
- package/deps/rocksdb/rocksdb/db/db_memtable_test.cc +2 -1
- package/deps/rocksdb/rocksdb/db/db_merge_operand_test.cc +42 -0
- package/deps/rocksdb/rocksdb/db/db_test.cc +61 -28
- package/deps/rocksdb/rocksdb/db/db_test2.cc +18 -7
- package/deps/rocksdb/rocksdb/db/db_wal_test.cc +17 -0
- package/deps/rocksdb/rocksdb/db/db_with_timestamp_compaction_test.cc +61 -0
- package/deps/rocksdb/rocksdb/db/db_write_test.cc +130 -0
- package/deps/rocksdb/rocksdb/db/experimental.cc +7 -8
- package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.cc +1 -2
- package/deps/rocksdb/rocksdb/db/flush_job.cc +11 -7
- package/deps/rocksdb/rocksdb/db/flush_job_test.cc +7 -1
- package/deps/rocksdb/rocksdb/db/forward_iterator.cc +4 -2
- package/deps/rocksdb/rocksdb/db/import_column_family_job.cc +1 -1
- package/deps/rocksdb/rocksdb/db/log_reader.cc +48 -11
- package/deps/rocksdb/rocksdb/db/log_reader.h +8 -2
- package/deps/rocksdb/rocksdb/db/log_test.cc +10 -1
- package/deps/rocksdb/rocksdb/db/log_writer.cc +7 -1
- package/deps/rocksdb/rocksdb/db/manual_compaction_test.cc +4 -4
- package/deps/rocksdb/rocksdb/db/memtable.cc +49 -14
- package/deps/rocksdb/rocksdb/db/memtable.h +60 -14
- package/deps/rocksdb/rocksdb/db/memtable_list.cc +14 -8
- package/deps/rocksdb/rocksdb/db/memtable_list_test.cc +30 -10
- package/deps/rocksdb/rocksdb/db/perf_context_test.cc +5 -5
- package/deps/rocksdb/rocksdb/db/pinned_iterators_manager.h +5 -0
- package/deps/rocksdb/rocksdb/db/repair.cc +2 -3
- package/deps/rocksdb/rocksdb/db/seqno_time_test.cc +3 -7
- package/deps/rocksdb/rocksdb/db/table_cache.cc +72 -0
- package/deps/rocksdb/rocksdb/db/table_cache.h +19 -1
- package/deps/rocksdb/rocksdb/db/table_cache_sync_and_async.h +8 -14
- package/deps/rocksdb/rocksdb/db/table_properties_collector_test.cc +2 -2
- package/deps/rocksdb/rocksdb/db/version_builder_test.cc +35 -64
- package/deps/rocksdb/rocksdb/db/version_edit.cc +3 -32
- package/deps/rocksdb/rocksdb/db/version_edit.h +2 -12
- package/deps/rocksdb/rocksdb/db/version_edit_test.cc +10 -23
- package/deps/rocksdb/rocksdb/db/version_set.cc +34 -10
- package/deps/rocksdb/rocksdb/db/version_set.h +3 -3
- package/deps/rocksdb/rocksdb/db/version_set_sync_and_async.h +5 -6
- package/deps/rocksdb/rocksdb/db/version_set_test.cc +17 -15
- package/deps/rocksdb/rocksdb/db/wal_manager.cc +0 -4
- package/deps/rocksdb/rocksdb/db/wal_manager_test.cc +2 -1
- package/deps/rocksdb/rocksdb/db/wide/db_wide_basic_test.cc +137 -42
- package/deps/rocksdb/rocksdb/db/wide/wide_column_serialization.cc +21 -0
- package/deps/rocksdb/rocksdb/db/wide/wide_column_serialization.h +1 -0
- package/deps/rocksdb/rocksdb/db/write_batch_test.cc +2 -1
- package/deps/rocksdb/rocksdb/db/write_callback_test.cc +4 -4
- package/deps/rocksdb/rocksdb/db/write_thread.cc +51 -46
- package/deps/rocksdb/rocksdb/db/write_thread.h +0 -4
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +4 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +6 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +6 -0
- package/deps/rocksdb/rocksdb/env/env_posix.cc +1 -1
- package/deps/rocksdb/rocksdb/env/env_test.cc +38 -8
- package/deps/rocksdb/rocksdb/env/file_system.cc +20 -0
- package/deps/rocksdb/rocksdb/env/fs_posix.cc +2 -46
- package/deps/rocksdb/rocksdb/env/io_posix.cc +1 -0
- package/deps/rocksdb/rocksdb/file/writable_file_writer.cc +110 -5
- package/deps/rocksdb/rocksdb/file/writable_file_writer.h +7 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/advanced_options.h +14 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/db.h +4 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/file_system.h +1 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/iostats_context.h +7 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/options.h +10 -3
- package/deps/rocksdb/rocksdb/include/rocksdb/slice.h +3 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/status.h +1 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/wide_columns.h +2 -0
- package/deps/rocksdb/rocksdb/logging/auto_roll_logger.cc +12 -0
- package/deps/rocksdb/rocksdb/logging/auto_roll_logger_test.cc +9 -13
- package/deps/rocksdb/rocksdb/logging/env_logger.h +39 -13
- package/deps/rocksdb/rocksdb/memtable/inlineskiplist.h +1 -1
- package/deps/rocksdb/rocksdb/memtable/write_buffer_manager_test.cc +1 -1
- package/deps/rocksdb/rocksdb/microbench/db_basic_bench.cc +6 -0
- package/deps/rocksdb/rocksdb/monitoring/iostats_context_imp.h +4 -1
- package/deps/rocksdb/rocksdb/options/cf_options.cc +6 -3
- package/deps/rocksdb/rocksdb/options/cf_options.h +6 -5
- package/deps/rocksdb/rocksdb/options/options_helper.cc +2 -1
- package/deps/rocksdb/rocksdb/options/options_settable_test.cc +1 -0
- package/deps/rocksdb/rocksdb/options/options_test.cc +4 -2
- package/deps/rocksdb/rocksdb/port/util_logger.h +1 -3
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +50 -8
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.h +4 -0
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_sync_and_async.h +7 -0
- package/deps/rocksdb/rocksdb/table/block_based/block_like_traits.h +28 -10
- package/deps/rocksdb/rocksdb/table/block_based/data_block_hash_index_test.cc +1 -1
- package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.cc +5 -2
- package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.h +1 -0
- package/deps/rocksdb/rocksdb/table/get_context.cc +16 -6
- package/deps/rocksdb/rocksdb/table/table_reader.h +9 -0
- package/deps/rocksdb/rocksdb/table/table_test.cc +2 -1
- package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +14 -1
- package/deps/rocksdb/rocksdb/tools/db_sanity_test.cc +5 -2
- package/deps/rocksdb/rocksdb/tools/ldb_cmd.cc +7 -8
- package/deps/rocksdb/rocksdb/tools/ldb_cmd_test.cc +6 -6
- package/deps/rocksdb/rocksdb/tools/reduce_levels_test.cc +1 -1
- package/deps/rocksdb/rocksdb/util/file_reader_writer_test.cc +2 -0
- package/deps/rocksdb/rocksdb/util/stderr_logger.h +13 -0
- package/deps/rocksdb/rocksdb/utilities/backup/backup_engine_test.cc +55 -46
- package/deps/rocksdb/rocksdb/utilities/cassandra/cassandra_functional_test.cc +2 -1
- package/deps/rocksdb/rocksdb/utilities/counted_fs.cc +10 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_locking_test.cc +2 -2
- package/deps/rocksdb/rocksdb/utilities/transactions/optimistic_transaction_test.cc +2 -2
- package/deps/rocksdb/rocksdb/utilities/ttl/ttl_test.cc +2 -2
- package/deps/rocksdb/rocksdb/utilities/write_batch_with_index/write_batch_with_index_test.cc +2 -2
- package/index.js +2 -2
- package/package.json +1 -1
- package/prebuilds/darwin-arm64/node.napi.node +0 -0
- package/prebuilds/linux-x64/node.napi.node +0 -0
- package/deps/rocksdb/rocksdb/logging/posix_logger.h +0 -179
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
diff --git a/logging/env_logger.h b/logging/env_logger.h
|
|
2
|
+
index b9099a834..0aa2b768a 100644
|
|
3
|
+
--- a/logging/env_logger.h
|
|
4
|
+
+++ b/logging/env_logger.h
|
|
5
|
+
@@ -57,12 +57,12 @@ class EnvLogger : public Logger {
|
|
6
|
+
// Preserve iostats not to pollute writes from user writes. We might
|
|
7
|
+
// need a better solution than this.
|
|
8
|
+
SetPerfLevel(PerfLevel::kDisable);
|
|
9
|
+
- iostats_context.disable_iostats = true;
|
|
10
|
+
+ // iostats_context.disable_iostats = true;
|
|
11
|
+
logger.mutex_.Lock();
|
|
12
|
+
}
|
|
13
|
+
~FileOpGuard() {
|
|
14
|
+
logger_.mutex_.Unlock();
|
|
15
|
+
- iostats_context.disable_iostats = false;
|
|
16
|
+
+ // iostats_context.disable_iostats = false;
|
|
17
|
+
SetPerfLevel(prev_perf_level_);
|
|
18
|
+
}
|
|
19
|
+
|
|
@@ -1009,7 +1009,7 @@ set(ROCKSDB_PLUGIN_BUILTINS "")
|
|
|
1009
1009
|
message(STATUS "ROCKSDB PLUGINS TO BUILD ${ROCKSDB_PLUGINS}")
|
|
1010
1010
|
list(APPEND PLUGINS ${ROCKSDB_PLUGINS})
|
|
1011
1011
|
foreach(PLUGIN IN LISTS PLUGINS)
|
|
1012
|
-
set(PLUGIN_ROOT "${
|
|
1012
|
+
set(PLUGIN_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/plugin/${PLUGIN}/")
|
|
1013
1013
|
message("including rocksb plugin ${PLUGIN_ROOT}")
|
|
1014
1014
|
set(PLUGINMKFILE "${PLUGIN_ROOT}${PLUGIN}.mk")
|
|
1015
1015
|
if (NOT EXISTS ${PLUGINMKFILE})
|
|
@@ -1509,6 +1509,20 @@ if(WITH_BENCHMARK_TOOLS)
|
|
|
1509
1509
|
${ROCKSDB_LIB} ${GFLAGS_LIB})
|
|
1510
1510
|
endif()
|
|
1511
1511
|
|
|
1512
|
+
option(WITH_TRACE_TOOLS "build with trace tools" ON)
|
|
1513
|
+
if(WITH_TRACE_TOOLS)
|
|
1514
|
+
add_executable(block_cache_trace_analyzer_tool${ARTIFACT_SUFFIX}
|
|
1515
|
+
tools/block_cache_analyzer/block_cache_trace_analyzer_tool.cc)
|
|
1516
|
+
target_link_libraries(block_cache_trace_analyzer_tool${ARTIFACT_SUFFIX}
|
|
1517
|
+
${ROCKSDB_LIB} ${GFLAGS_LIB})
|
|
1518
|
+
|
|
1519
|
+
add_executable(trace_analyzer${ARTIFACT_SUFFIX}
|
|
1520
|
+
tools/trace_analyzer.cc)
|
|
1521
|
+
target_link_libraries(trace_analyzer${ARTIFACT_SUFFIX}
|
|
1522
|
+
${ROCKSDB_LIB} ${GFLAGS_LIB})
|
|
1523
|
+
|
|
1524
|
+
endif()
|
|
1525
|
+
|
|
1512
1526
|
if(WITH_CORE_TOOLS OR WITH_TOOLS)
|
|
1513
1527
|
add_subdirectory(tools)
|
|
1514
1528
|
add_custom_target(core_tools
|
|
@@ -23,6 +23,11 @@
|
|
|
23
23
|
#include "util/coding.h"
|
|
24
24
|
#include "util/string_util.h"
|
|
25
25
|
|
|
26
|
+
// FastLRUCache and ClockCache only support 16-byte keys, so some of
|
|
27
|
+
// the tests originally wrote for LRUCache do not work on the other caches.
|
|
28
|
+
// Those tests were adapted to use 16-byte keys. We kept the original ones.
|
|
29
|
+
// TODO: Remove the original tests if they ever become unused.
|
|
30
|
+
|
|
26
31
|
namespace ROCKSDB_NAMESPACE {
|
|
27
32
|
|
|
28
33
|
namespace {
|
|
@@ -58,17 +63,22 @@ int DecodeValue(void* v) {
|
|
|
58
63
|
return static_cast<int>(reinterpret_cast<uintptr_t>(v));
|
|
59
64
|
}
|
|
60
65
|
|
|
61
|
-
const
|
|
62
|
-
const std::string kClock = "clock";
|
|
63
|
-
const std::string kFast = "fast";
|
|
64
|
-
|
|
65
|
-
void dumbDeleter(const Slice& /*key*/, void* /*value*/) {}
|
|
66
|
+
void DumbDeleter(const Slice& /*key*/, void* /*value*/) {}
|
|
66
67
|
|
|
67
|
-
void
|
|
68
|
+
void EraseDeleter1(const Slice& /*key*/, void* value) {
|
|
68
69
|
Cache* cache = reinterpret_cast<Cache*>(value);
|
|
69
70
|
cache->Erase("foo");
|
|
70
71
|
}
|
|
71
72
|
|
|
73
|
+
void EraseDeleter2(const Slice& /*key*/, void* value) {
|
|
74
|
+
Cache* cache = reinterpret_cast<Cache*>(value);
|
|
75
|
+
cache->Erase(EncodeKey16Bytes(1234));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const std::string kLRU = "lru";
|
|
79
|
+
const std::string kClock = "clock";
|
|
80
|
+
const std::string kFast = "fast";
|
|
81
|
+
|
|
72
82
|
} // anonymous namespace
|
|
73
83
|
|
|
74
84
|
class CacheTest : public testing::TestWithParam<std::string> {
|
|
@@ -223,13 +233,9 @@ class LRUCacheTest : public CacheTest {};
|
|
|
223
233
|
|
|
224
234
|
TEST_P(CacheTest, UsageTest) {
|
|
225
235
|
auto type = GetParam();
|
|
226
|
-
if (type == kFast || type == kClock) {
|
|
227
|
-
ROCKSDB_GTEST_BYPASS("FastLRUCache and ClockCache require 16-byte keys.");
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
236
|
|
|
231
237
|
// cache is std::shared_ptr and will be automatically cleaned up.
|
|
232
|
-
const
|
|
238
|
+
const size_t kCapacity = 100000;
|
|
233
239
|
auto cache = NewCache(kCapacity, 8, false, kDontChargeCacheMetadata);
|
|
234
240
|
auto precise_cache = NewCache(kCapacity, 0, false, kFullChargeCacheMetadata);
|
|
235
241
|
ASSERT_EQ(0, cache->GetUsage());
|
|
@@ -239,12 +245,17 @@ TEST_P(CacheTest, UsageTest) {
|
|
|
239
245
|
char value[10] = "abcdef";
|
|
240
246
|
// make sure everything will be cached
|
|
241
247
|
for (int i = 1; i < 100; ++i) {
|
|
242
|
-
std::string key
|
|
248
|
+
std::string key;
|
|
249
|
+
if (type == kLRU) {
|
|
250
|
+
key = std::string(i, 'a');
|
|
251
|
+
} else {
|
|
252
|
+
key = EncodeKey(i);
|
|
253
|
+
}
|
|
243
254
|
auto kv_size = key.size() + 5;
|
|
244
255
|
ASSERT_OK(cache->Insert(key, reinterpret_cast<void*>(value), kv_size,
|
|
245
|
-
|
|
256
|
+
DumbDeleter));
|
|
246
257
|
ASSERT_OK(precise_cache->Insert(key, reinterpret_cast<void*>(value),
|
|
247
|
-
kv_size,
|
|
258
|
+
kv_size, DumbDeleter));
|
|
248
259
|
usage += kv_size;
|
|
249
260
|
ASSERT_EQ(usage, cache->GetUsage());
|
|
250
261
|
ASSERT_LT(usage, precise_cache->GetUsage());
|
|
@@ -256,12 +267,17 @@ TEST_P(CacheTest, UsageTest) {
|
|
|
256
267
|
ASSERT_EQ(0, precise_cache->GetUsage());
|
|
257
268
|
|
|
258
269
|
// make sure the cache will be overloaded
|
|
259
|
-
for (
|
|
260
|
-
|
|
270
|
+
for (size_t i = 1; i < kCapacity; ++i) {
|
|
271
|
+
std::string key;
|
|
272
|
+
if (type == kLRU) {
|
|
273
|
+
key = std::to_string(i);
|
|
274
|
+
} else {
|
|
275
|
+
key = EncodeKey(static_cast<int>(1000 + i));
|
|
276
|
+
}
|
|
261
277
|
ASSERT_OK(cache->Insert(key, reinterpret_cast<void*>(value), key.size() + 5,
|
|
262
|
-
|
|
278
|
+
DumbDeleter));
|
|
263
279
|
ASSERT_OK(precise_cache->Insert(key, reinterpret_cast<void*>(value),
|
|
264
|
-
key.size() + 5,
|
|
280
|
+
key.size() + 5, DumbDeleter));
|
|
265
281
|
}
|
|
266
282
|
|
|
267
283
|
// the usage should be close to the capacity
|
|
@@ -271,15 +287,18 @@ TEST_P(CacheTest, UsageTest) {
|
|
|
271
287
|
ASSERT_LT(kCapacity * 0.95, precise_cache->GetUsage());
|
|
272
288
|
}
|
|
273
289
|
|
|
290
|
+
// TODO: This test takes longer than expected on ClockCache. This is
|
|
291
|
+
// because the values size estimate at construction is too sloppy.
|
|
292
|
+
// Fix this.
|
|
293
|
+
// Why is it so slow? The cache is constructed with an estimate of 1, but
|
|
294
|
+
// then the charge is claimed to be 21. This will cause the hash table
|
|
295
|
+
// to be extremely sparse, which in turn means clock needs to scan too
|
|
296
|
+
// many slots to find victims.
|
|
274
297
|
TEST_P(CacheTest, PinnedUsageTest) {
|
|
275
298
|
auto type = GetParam();
|
|
276
|
-
if (type == kFast || type == kClock) {
|
|
277
|
-
ROCKSDB_GTEST_BYPASS("FastLRUCache and ClockCache require 16-byte keys.");
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
280
299
|
|
|
281
300
|
// cache is std::shared_ptr and will be automatically cleaned up.
|
|
282
|
-
const
|
|
301
|
+
const size_t kCapacity = 200000;
|
|
283
302
|
auto cache = NewCache(kCapacity, 8, false, kDontChargeCacheMetadata);
|
|
284
303
|
auto precise_cache = NewCache(kCapacity, 8, false, kFullChargeCacheMetadata);
|
|
285
304
|
|
|
@@ -292,15 +311,20 @@ TEST_P(CacheTest, PinnedUsageTest) {
|
|
|
292
311
|
// Add entries. Unpin some of them after insertion. Then, pin some of them
|
|
293
312
|
// again. Check GetPinnedUsage().
|
|
294
313
|
for (int i = 1; i < 100; ++i) {
|
|
295
|
-
std::string key
|
|
314
|
+
std::string key;
|
|
315
|
+
if (type == kLRU) {
|
|
316
|
+
key = std::string(i, 'a');
|
|
317
|
+
} else {
|
|
318
|
+
key = EncodeKey(i);
|
|
319
|
+
}
|
|
296
320
|
auto kv_size = key.size() + 5;
|
|
297
321
|
Cache::Handle* handle;
|
|
298
322
|
Cache::Handle* handle_in_precise_cache;
|
|
299
323
|
ASSERT_OK(cache->Insert(key, reinterpret_cast<void*>(value), kv_size,
|
|
300
|
-
|
|
324
|
+
DumbDeleter, &handle));
|
|
301
325
|
assert(handle);
|
|
302
326
|
ASSERT_OK(precise_cache->Insert(key, reinterpret_cast<void*>(value),
|
|
303
|
-
kv_size,
|
|
327
|
+
kv_size, DumbDeleter,
|
|
304
328
|
&handle_in_precise_cache));
|
|
305
329
|
assert(handle_in_precise_cache);
|
|
306
330
|
pinned_usage += kv_size;
|
|
@@ -334,12 +358,17 @@ TEST_P(CacheTest, PinnedUsageTest) {
|
|
|
334
358
|
ASSERT_LT(pinned_usage, precise_cache_pinned_usage);
|
|
335
359
|
|
|
336
360
|
// check that overloading the cache does not change the pinned usage
|
|
337
|
-
for (
|
|
338
|
-
|
|
361
|
+
for (size_t i = 1; i < 2 * kCapacity; ++i) {
|
|
362
|
+
std::string key;
|
|
363
|
+
if (type == kLRU) {
|
|
364
|
+
key = std::to_string(i);
|
|
365
|
+
} else {
|
|
366
|
+
key = EncodeKey(static_cast<int>(1000 + i));
|
|
367
|
+
}
|
|
339
368
|
ASSERT_OK(cache->Insert(key, reinterpret_cast<void*>(value), key.size() + 5,
|
|
340
|
-
|
|
369
|
+
DumbDeleter));
|
|
341
370
|
ASSERT_OK(precise_cache->Insert(key, reinterpret_cast<void*>(value),
|
|
342
|
-
key.size() + 5,
|
|
371
|
+
key.size() + 5, DumbDeleter));
|
|
343
372
|
}
|
|
344
373
|
ASSERT_EQ(pinned_usage, cache->GetPinnedUsage());
|
|
345
374
|
ASSERT_EQ(precise_cache_pinned_usage, precise_cache->GetPinnedUsage());
|
|
@@ -447,7 +476,7 @@ TEST_P(CacheTest, EvictionPolicy) {
|
|
|
447
476
|
Insert(200, 201);
|
|
448
477
|
|
|
449
478
|
// Frequently used entry must be kept around
|
|
450
|
-
for (int i = 0; i <
|
|
479
|
+
for (int i = 0; i < 2 * kCacheSize; i++) {
|
|
451
480
|
Insert(1000+i, 2000+i);
|
|
452
481
|
ASSERT_EQ(101, Lookup(100));
|
|
453
482
|
}
|
|
@@ -500,9 +529,7 @@ TEST_P(CacheTest, EvictionPolicyRef) {
|
|
|
500
529
|
Insert(303, 104);
|
|
501
530
|
|
|
502
531
|
// Insert entries much more than cache capacity.
|
|
503
|
-
|
|
504
|
-
std::min(fast_lru_cache::kLoadFactor, clock_cache::kLoadFactor);
|
|
505
|
-
for (int i = 0; i < 2 * static_cast<int>(kCacheSize / load_factor); i++) {
|
|
532
|
+
for (int i = 0; i < 100 * kCacheSize; i++) {
|
|
506
533
|
Insert(1000 + i, 2000 + i);
|
|
507
534
|
}
|
|
508
535
|
|
|
@@ -533,31 +560,40 @@ TEST_P(CacheTest, EvictionPolicyRef) {
|
|
|
533
560
|
|
|
534
561
|
TEST_P(CacheTest, EvictEmptyCache) {
|
|
535
562
|
auto type = GetParam();
|
|
536
|
-
if (type == kFast || type == kClock) {
|
|
537
|
-
ROCKSDB_GTEST_BYPASS("FastLRUCache and ClockCache require 16-byte keys.");
|
|
538
|
-
return;
|
|
539
|
-
}
|
|
540
563
|
|
|
541
564
|
// Insert item large than capacity to trigger eviction on empty cache.
|
|
542
565
|
auto cache = NewCache(1, 0, false);
|
|
543
|
-
|
|
566
|
+
if (type == kLRU) {
|
|
567
|
+
ASSERT_OK(cache->Insert("foo", nullptr, 10, DumbDeleter));
|
|
568
|
+
} else {
|
|
569
|
+
ASSERT_OK(cache->Insert(EncodeKey(1000), nullptr, 10, DumbDeleter));
|
|
570
|
+
}
|
|
544
571
|
}
|
|
545
572
|
|
|
546
573
|
TEST_P(CacheTest, EraseFromDeleter) {
|
|
547
574
|
auto type = GetParam();
|
|
548
|
-
if (type == kFast || type == kClock) {
|
|
549
|
-
ROCKSDB_GTEST_BYPASS("FastLRUCache and ClockCache require 16-byte keys.");
|
|
550
|
-
return;
|
|
551
|
-
}
|
|
552
575
|
|
|
553
576
|
// Have deleter which will erase item from cache, which will re-enter
|
|
554
577
|
// the cache at that point.
|
|
555
578
|
std::shared_ptr<Cache> cache = NewCache(10, 0, false);
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
579
|
+
std::string foo, bar;
|
|
580
|
+
Cache::DeleterFn erase_deleter;
|
|
581
|
+
if (type == kLRU) {
|
|
582
|
+
foo = "foo";
|
|
583
|
+
bar = "bar";
|
|
584
|
+
erase_deleter = EraseDeleter1;
|
|
585
|
+
} else {
|
|
586
|
+
foo = EncodeKey(1234);
|
|
587
|
+
bar = EncodeKey(5678);
|
|
588
|
+
erase_deleter = EraseDeleter2;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
ASSERT_OK(cache->Insert(foo, nullptr, 1, DumbDeleter));
|
|
592
|
+
ASSERT_OK(cache->Insert(bar, cache.get(), 1, erase_deleter));
|
|
593
|
+
|
|
594
|
+
cache->Erase(bar);
|
|
595
|
+
ASSERT_EQ(nullptr, cache->Lookup(foo));
|
|
596
|
+
ASSERT_EQ(nullptr, cache->Lookup(bar));
|
|
561
597
|
}
|
|
562
598
|
|
|
563
599
|
TEST_P(CacheTest, ErasedHandleState) {
|
|
@@ -590,9 +626,9 @@ TEST_P(CacheTest, HeavyEntries) {
|
|
|
590
626
|
const int kHeavy = 10;
|
|
591
627
|
int added = 0;
|
|
592
628
|
int index = 0;
|
|
593
|
-
while (added < 2*kCacheSize) {
|
|
629
|
+
while (added < 2 * kCacheSize) {
|
|
594
630
|
const int weight = (index & 1) ? kLight : kHeavy;
|
|
595
|
-
Insert(index, 1000+index, weight);
|
|
631
|
+
Insert(index, 1000 + index, weight);
|
|
596
632
|
added += weight;
|
|
597
633
|
index++;
|
|
598
634
|
}
|
|
@@ -603,7 +639,7 @@ TEST_P(CacheTest, HeavyEntries) {
|
|
|
603
639
|
int r = Lookup(i);
|
|
604
640
|
if (r >= 0) {
|
|
605
641
|
cached_weight += weight;
|
|
606
|
-
ASSERT_EQ(1000+i, r);
|
|
642
|
+
ASSERT_EQ(1000 + i, r);
|
|
607
643
|
}
|
|
608
644
|
}
|
|
609
645
|
ASSERT_LE(cached_weight, kCacheSize + kCacheSize/10);
|
|
@@ -615,7 +651,6 @@ TEST_P(CacheTest, NewId) {
|
|
|
615
651
|
ASSERT_NE(a, b);
|
|
616
652
|
}
|
|
617
653
|
|
|
618
|
-
|
|
619
654
|
class Value {
|
|
620
655
|
public:
|
|
621
656
|
explicit Value(int v) : v_(v) {}
|
|
@@ -664,7 +699,8 @@ TEST_P(CacheTest, SetCapacity) {
|
|
|
664
699
|
auto type = GetParam();
|
|
665
700
|
if (type == kFast || type == kClock) {
|
|
666
701
|
ROCKSDB_GTEST_BYPASS(
|
|
667
|
-
"FastLRUCache and ClockCache don't support capacity
|
|
702
|
+
"FastLRUCache and ClockCache don't support arbitrary capacity "
|
|
703
|
+
"adjustments.");
|
|
668
704
|
return;
|
|
669
705
|
}
|
|
670
706
|
// test1: increase capacity
|
|
@@ -716,9 +752,9 @@ TEST_P(CacheTest, SetCapacity) {
|
|
|
716
752
|
|
|
717
753
|
TEST_P(LRUCacheTest, SetStrictCapacityLimit) {
|
|
718
754
|
auto type = GetParam();
|
|
719
|
-
if (type == kFast
|
|
755
|
+
if (type == kFast) {
|
|
720
756
|
ROCKSDB_GTEST_BYPASS(
|
|
721
|
-
"FastLRUCache
|
|
757
|
+
"FastLRUCache only supports a limited number of "
|
|
722
758
|
"inserts beyond "
|
|
723
759
|
"capacity.");
|
|
724
760
|
return;
|
|
@@ -775,9 +811,8 @@ TEST_P(LRUCacheTest, SetStrictCapacityLimit) {
|
|
|
775
811
|
|
|
776
812
|
TEST_P(CacheTest, OverCapacity) {
|
|
777
813
|
auto type = GetParam();
|
|
778
|
-
if (type ==
|
|
779
|
-
ROCKSDB_GTEST_BYPASS(
|
|
780
|
-
"FastLRUCache and ClockCache don't support capacity adjustments.");
|
|
814
|
+
if (type == kClock) {
|
|
815
|
+
ROCKSDB_GTEST_BYPASS("Requires LRU eviction policy.");
|
|
781
816
|
return;
|
|
782
817
|
}
|
|
783
818
|
size_t n = 10;
|
|
@@ -69,10 +69,10 @@ ClockHandle* ClockHandleTable::Lookup(const Slice& key, uint32_t hash) {
|
|
|
69
69
|
// updates where it would be possible to combine into one CAS (more metadata
|
|
70
70
|
// under one atomic field) or maybe two atomic updates (one arithmetic, one
|
|
71
71
|
// bitwise). Something to think about optimizing.
|
|
72
|
-
e->InternalToExternalRef();
|
|
73
72
|
e->SetHit();
|
|
74
73
|
// The handle is now referenced, so we take it out of clock.
|
|
75
74
|
ClockOff(e);
|
|
75
|
+
e->InternalToExternalRef();
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
return e;
|
|
@@ -312,17 +312,20 @@ void ClockHandleTable::ClockRun(size_t charge) {
|
|
|
312
312
|
// hot element, it will be hard to get an exclusive ref.
|
|
313
313
|
// Do we need a mechanism to prevent an element from sitting
|
|
314
314
|
// for a long time in cache waiting to be evicted?
|
|
315
|
-
assert(charge <= capacity_);
|
|
316
315
|
autovector<ClockHandle> deleted;
|
|
317
316
|
uint32_t max_iterations =
|
|
318
|
-
|
|
317
|
+
ClockHandle::ClockPriority::HIGH *
|
|
318
|
+
(1 +
|
|
319
|
+
static_cast<uint32_t>(
|
|
320
|
+
GetTableSize() *
|
|
321
|
+
kLoadFactor)); // It may take up to HIGH passes to evict an element.
|
|
319
322
|
size_t usage_local = usage_;
|
|
320
|
-
|
|
323
|
+
size_t capacity_local = capacity_;
|
|
324
|
+
while (usage_local + charge > capacity_local && max_iterations--) {
|
|
321
325
|
uint32_t steps = 1 + static_cast<uint32_t>(1 / kLoadFactor);
|
|
322
326
|
uint32_t clock_pointer_local = (clock_pointer_ += steps) - steps;
|
|
323
327
|
for (uint32_t i = 0; i < steps; i++) {
|
|
324
328
|
ClockHandle* h = &array_[ModTableSize(clock_pointer_local + i)];
|
|
325
|
-
|
|
326
329
|
if (h->TryExclusiveRef()) {
|
|
327
330
|
if (h->WillBeDeleted()) {
|
|
328
331
|
Remove(h, &deleted);
|
|
@@ -335,7 +338,6 @@ void ClockHandleTable::ClockRun(size_t charge) {
|
|
|
335
338
|
// exclusive ref, we know we are in the latter case. This can only
|
|
336
339
|
// happen when the last external reference to an element was
|
|
337
340
|
// released, and the element was not immediately removed.
|
|
338
|
-
|
|
339
341
|
ClockOn(h);
|
|
340
342
|
}
|
|
341
343
|
ClockHandle::ClockPriority priority = h->GetClockPriority();
|
|
@@ -358,6 +360,7 @@ ClockCacheShard::ClockCacheShard(
|
|
|
358
360
|
size_t capacity, size_t estimated_value_size, bool strict_capacity_limit,
|
|
359
361
|
CacheMetadataChargePolicy metadata_charge_policy)
|
|
360
362
|
: strict_capacity_limit_(strict_capacity_limit),
|
|
363
|
+
detached_usage_(0),
|
|
361
364
|
table_(capacity, CalcHashBits(capacity, estimated_value_size,
|
|
362
365
|
metadata_charge_policy)) {
|
|
363
366
|
set_metadata_charge_policy(metadata_charge_policy);
|
|
@@ -401,15 +404,24 @@ void ClockCacheShard::ApplyToSomeEntries(
|
|
|
401
404
|
*state = index_end << (32 - length_bits);
|
|
402
405
|
}
|
|
403
406
|
|
|
404
|
-
table_.
|
|
407
|
+
table_.ConstApplyToEntriesRange(
|
|
405
408
|
[callback,
|
|
406
|
-
metadata_charge_policy = metadata_charge_policy_](ClockHandle* h) {
|
|
409
|
+
metadata_charge_policy = metadata_charge_policy_](const ClockHandle* h) {
|
|
407
410
|
callback(h->key(), h->value, h->GetCharge(metadata_charge_policy),
|
|
408
411
|
h->deleter);
|
|
409
412
|
},
|
|
410
413
|
index_begin, index_end, false);
|
|
411
414
|
}
|
|
412
415
|
|
|
416
|
+
ClockHandle* ClockCacheShard::DetachedInsert(ClockHandle* h) {
|
|
417
|
+
ClockHandle* e = new ClockHandle();
|
|
418
|
+
*e = *h;
|
|
419
|
+
e->SetDetached();
|
|
420
|
+
e->TryExternalRef();
|
|
421
|
+
detached_usage_ += h->total_charge;
|
|
422
|
+
return e;
|
|
423
|
+
}
|
|
424
|
+
|
|
413
425
|
size_t ClockCacheShard::CalcEstimatedHandleCharge(
|
|
414
426
|
size_t estimated_value_size,
|
|
415
427
|
CacheMetadataChargePolicy metadata_charge_policy) {
|
|
@@ -430,12 +442,16 @@ int ClockCacheShard::CalcHashBits(
|
|
|
430
442
|
return FloorLog2((num_entries << 1) - 1);
|
|
431
443
|
}
|
|
432
444
|
|
|
433
|
-
void ClockCacheShard::SetCapacity(size_t
|
|
434
|
-
|
|
445
|
+
void ClockCacheShard::SetCapacity(size_t capacity) {
|
|
446
|
+
if (capacity > table_.GetCapacity()) {
|
|
447
|
+
assert(false); // Not supported.
|
|
448
|
+
}
|
|
449
|
+
table_.SetCapacity(capacity);
|
|
450
|
+
table_.ClockRun(detached_usage_);
|
|
435
451
|
}
|
|
436
452
|
|
|
437
|
-
void ClockCacheShard::SetStrictCapacityLimit(bool
|
|
438
|
-
|
|
453
|
+
void ClockCacheShard::SetStrictCapacityLimit(bool strict_capacity_limit) {
|
|
454
|
+
strict_capacity_limit_ = strict_capacity_limit;
|
|
439
455
|
}
|
|
440
456
|
|
|
441
457
|
Status ClockCacheShard::Insert(const Slice& key, uint32_t hash, void* value,
|
|
@@ -459,27 +475,32 @@ Status ClockCacheShard::Insert(const Slice& key, uint32_t hash, void* value,
|
|
|
459
475
|
|
|
460
476
|
Status s = Status::OK();
|
|
461
477
|
|
|
478
|
+
// Use a local copy to minimize cache synchronization.
|
|
479
|
+
size_t detached_usage = detached_usage_;
|
|
480
|
+
|
|
462
481
|
// Free space with the clock policy until enough space is freed or there are
|
|
463
482
|
// no evictable elements.
|
|
464
|
-
table_.ClockRun(tmp.total_charge);
|
|
483
|
+
table_.ClockRun(tmp.total_charge + detached_usage);
|
|
465
484
|
|
|
466
|
-
//
|
|
467
|
-
//
|
|
485
|
+
// Use local copies to minimize cache synchronization
|
|
486
|
+
// (occupancy_ and usage_ are read and written by all insertions).
|
|
468
487
|
uint32_t occupancy_local = table_.GetOccupancy();
|
|
469
|
-
size_t
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
488
|
+
size_t total_usage = table_.GetUsage() + detached_usage;
|
|
489
|
+
|
|
490
|
+
// TODO: Currently we support strict_capacity_limit == false as long as the
|
|
491
|
+
// number of pinned elements is below table_.GetOccupancyLimit(). We can
|
|
492
|
+
// always support it as follows: whenever we exceed this limit, we dynamically
|
|
493
|
+
// allocate a handle and return it (when the user provides a handle pointer,
|
|
494
|
+
// of course). Then, Release checks whether the handle was dynamically
|
|
495
|
+
// allocated, or is stored in the table.
|
|
496
|
+
if (total_usage + tmp.total_charge > table_.GetCapacity() &&
|
|
497
|
+
(strict_capacity_limit_ || handle == nullptr)) {
|
|
477
498
|
if (handle == nullptr) {
|
|
478
499
|
// Don't insert the entry but still return ok, as if the entry inserted
|
|
479
500
|
// into cache and get evicted immediately.
|
|
480
|
-
|
|
501
|
+
tmp.FreeData();
|
|
481
502
|
} else {
|
|
482
|
-
if (occupancy_local > table_.GetOccupancyLimit()) {
|
|
503
|
+
if (occupancy_local + 1 > table_.GetOccupancyLimit()) {
|
|
483
504
|
// TODO: Consider using a distinct status for this case, but usually
|
|
484
505
|
// it will be handled the same way as reaching charge capacity limit
|
|
485
506
|
s = Status::MemoryLimit(
|
|
@@ -491,22 +512,34 @@ Status ClockCacheShard::Insert(const Slice& key, uint32_t hash, void* value,
|
|
|
491
512
|
}
|
|
492
513
|
}
|
|
493
514
|
} else {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
515
|
+
ClockHandle* h = nullptr;
|
|
516
|
+
if (handle != nullptr && occupancy_local + 1 > table_.GetOccupancyLimit()) {
|
|
517
|
+
// Even if the user wishes to overload the cache, we can't insert into
|
|
518
|
+
// the hash table. Instead, we dynamically allocate a new handle.
|
|
519
|
+
h = DetachedInsert(&tmp);
|
|
520
|
+
// TODO: Return special status?
|
|
521
|
+
} else {
|
|
522
|
+
// Insert into the cache. Note that the cache might get larger than its
|
|
523
|
+
// capacity if not enough space was freed up.
|
|
524
|
+
autovector<ClockHandle> deleted;
|
|
525
|
+
h = table_.Insert(&tmp, &deleted, handle != nullptr);
|
|
526
|
+
if (h == nullptr && handle != nullptr) {
|
|
527
|
+
// The table is full. This can happen when many threads simultaneously
|
|
528
|
+
// attempt an insert, and the table is operating close to full capacity.
|
|
529
|
+
h = DetachedInsert(&tmp);
|
|
530
|
+
}
|
|
531
|
+
// Notice that if handle == nullptr, we don't insert the entry but still
|
|
532
|
+
// return ok.
|
|
533
|
+
if (deleted.size() > 0) {
|
|
534
|
+
s = Status::OkOverwritten();
|
|
535
|
+
}
|
|
536
|
+
table_.Free(&deleted);
|
|
537
|
+
}
|
|
499
538
|
if (handle != nullptr) {
|
|
500
539
|
*handle = reinterpret_cast<Cache::Handle*>(h);
|
|
501
540
|
}
|
|
502
|
-
|
|
503
|
-
if (deleted.size() > 0) {
|
|
504
|
-
s = Status::OkOverwritten();
|
|
505
|
-
}
|
|
506
541
|
}
|
|
507
542
|
|
|
508
|
-
table_.Free(&deleted);
|
|
509
|
-
|
|
510
543
|
return s;
|
|
511
544
|
}
|
|
512
545
|
|
|
@@ -516,7 +549,7 @@ Cache::Handle* ClockCacheShard::Lookup(const Slice& key, uint32_t hash) {
|
|
|
516
549
|
|
|
517
550
|
bool ClockCacheShard::Ref(Cache::Handle* h) {
|
|
518
551
|
ClockHandle* e = reinterpret_cast<ClockHandle*>(h);
|
|
519
|
-
assert(e->
|
|
552
|
+
assert(e->ExternalRefs() > 0);
|
|
520
553
|
return e->TryExternalRef();
|
|
521
554
|
}
|
|
522
555
|
|
|
@@ -530,6 +563,20 @@ bool ClockCacheShard::Release(Cache::Handle* handle, bool erase_if_last_ref) {
|
|
|
530
563
|
}
|
|
531
564
|
|
|
532
565
|
ClockHandle* h = reinterpret_cast<ClockHandle*>(handle);
|
|
566
|
+
|
|
567
|
+
if (UNLIKELY(h->IsDetached())) {
|
|
568
|
+
h->ReleaseExternalRef();
|
|
569
|
+
if (h->TryExclusiveRef()) {
|
|
570
|
+
// Only the last reference will succeed.
|
|
571
|
+
// Don't bother releasing the exclusive ref.
|
|
572
|
+
h->FreeData();
|
|
573
|
+
detached_usage_ -= h->total_charge;
|
|
574
|
+
delete h;
|
|
575
|
+
return true;
|
|
576
|
+
}
|
|
577
|
+
return false;
|
|
578
|
+
}
|
|
579
|
+
|
|
533
580
|
uint32_t refs = h->refs;
|
|
534
581
|
bool last_reference = ((refs & ClockHandle::EXTERNAL_REFS) == 1);
|
|
535
582
|
bool will_be_deleted = refs & ClockHandle::WILL_BE_DELETED;
|
|
@@ -569,14 +616,15 @@ size_t ClockCacheShard::GetPinnedUsage() const {
|
|
|
569
616
|
size_t clock_usage = 0;
|
|
570
617
|
|
|
571
618
|
table_.ConstApplyToEntriesRange(
|
|
572
|
-
[&clock_usage](ClockHandle* h) {
|
|
573
|
-
if (h->
|
|
619
|
+
[&clock_usage](const ClockHandle* h) {
|
|
620
|
+
if (h->ExternalRefs() > 1) {
|
|
621
|
+
// We check > 1 because we are holding an external ref.
|
|
574
622
|
clock_usage += h->total_charge;
|
|
575
623
|
}
|
|
576
624
|
},
|
|
577
625
|
0, table_.GetTableSize(), true);
|
|
578
626
|
|
|
579
|
-
return clock_usage;
|
|
627
|
+
return clock_usage + detached_usage_;
|
|
580
628
|
}
|
|
581
629
|
|
|
582
630
|
ClockCache::ClockCache(size_t capacity, size_t estimated_value_size,
|