@nxtedition/rocksdb 7.1.20 → 7.1.21
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/CMakeLists.txt +13 -6
- package/deps/rocksdb/rocksdb/Makefile +1 -1
- package/deps/rocksdb/rocksdb/TARGETS +2 -0
- package/deps/rocksdb/rocksdb/cache/cache_reservation_manager_test.cc +1 -0
- package/deps/rocksdb/rocksdb/cache/cache_test.cc +4 -4
- package/deps/rocksdb/rocksdb/cache/clock_cache.cc +139 -161
- package/deps/rocksdb/rocksdb/cache/clock_cache.h +92 -82
- package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache.cc +16 -3
- package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache.h +9 -3
- package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache_test.cc +73 -30
- package/deps/rocksdb/rocksdb/cache/fast_lru_cache.cc +25 -67
- package/deps/rocksdb/rocksdb/cache/fast_lru_cache.h +41 -40
- package/deps/rocksdb/rocksdb/cache/lru_cache.cc +109 -155
- package/deps/rocksdb/rocksdb/cache/lru_cache.h +127 -149
- package/deps/rocksdb/rocksdb/cache/lru_cache_test.cc +75 -80
- package/deps/rocksdb/rocksdb/cache/sharded_cache.cc +22 -172
- package/deps/rocksdb/rocksdb/cache/sharded_cache.h +272 -85
- package/deps/rocksdb/rocksdb/db/arena_wrapped_db_iter.cc +12 -4
- package/deps/rocksdb/rocksdb/db/blob/blob_counting_iterator_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/blob/blob_file_addition_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/blob/blob_file_builder_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/blob/blob_file_cache_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/blob/blob_file_garbage_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/blob/blob_file_reader_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/blob/blob_garbage_meter_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/blob/blob_source_test.cc +13 -4
- package/deps/rocksdb/rocksdb/db/builder.cc +1 -1
- package/deps/rocksdb/rocksdb/db/column_family.cc +15 -1
- package/deps/rocksdb/rocksdb/db/compact_files_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/compaction/clipping_iterator_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction.cc +25 -7
- package/deps/rocksdb/rocksdb/db/compaction/compaction.h +10 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.cc +22 -8
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.h +14 -5
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +38 -12
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job.h +9 -6
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job_test.cc +408 -6
- package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.cc +244 -54
- package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.h +27 -6
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.cc +25 -30
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.cc +87 -26
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_level.cc +23 -4
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_test.cc +61 -0
- package/deps/rocksdb/rocksdb/db/compaction/tiered_compaction_test.cc +294 -21
- package/deps/rocksdb/rocksdb/db/comparator_db_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/cuckoo_table_db_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/db_block_cache_test.cc +28 -10
- package/deps/rocksdb/rocksdb/db/db_bloom_filter_test.cc +4 -4
- package/deps/rocksdb/rocksdb/db/db_compaction_test.cc +272 -0
- package/deps/rocksdb/rocksdb/db/db_flush_test.cc +38 -0
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +69 -25
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +7 -3
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +29 -12
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_debug.cc +0 -12
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_files.cc +10 -4
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +35 -22
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_secondary.cc +5 -1
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_write.cc +40 -5
- package/deps/rocksdb/rocksdb/db/db_iter.cc +1 -0
- package/deps/rocksdb/rocksdb/db/db_iter_stress_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/db_iter_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/db_iterator_test.cc +22 -0
- package/deps/rocksdb/rocksdb/db/db_kv_checksum_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/db_logical_block_size_cache_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/db_range_del_test.cc +72 -5
- package/deps/rocksdb/rocksdb/db/db_tailing_iter_test.cc +60 -21
- package/deps/rocksdb/rocksdb/db/db_test.cc +170 -1
- package/deps/rocksdb/rocksdb/db/db_test2.cc +9 -3
- package/deps/rocksdb/rocksdb/db/db_test_util.cc +19 -0
- package/deps/rocksdb/rocksdb/db/db_test_util.h +32 -0
- package/deps/rocksdb/rocksdb/db/db_with_timestamp_basic_test.cc +444 -3
- package/deps/rocksdb/rocksdb/db/db_write_test.cc +8 -8
- package/deps/rocksdb/rocksdb/db/dbformat.cc +13 -0
- package/deps/rocksdb/rocksdb/db/dbformat.h +59 -4
- package/deps/rocksdb/rocksdb/db/dbformat_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/experimental.cc +3 -1
- package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.cc +24 -3
- package/deps/rocksdb/rocksdb/db/fault_injection_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/filename_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/flush_job.cc +4 -3
- package/deps/rocksdb/rocksdb/db/flush_job_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/forward_iterator.cc +85 -43
- package/deps/rocksdb/rocksdb/db/forward_iterator.h +3 -1
- package/deps/rocksdb/rocksdb/db/internal_stats.cc +33 -6
- package/deps/rocksdb/rocksdb/db/internal_stats.h +6 -0
- package/deps/rocksdb/rocksdb/db/listener_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/log_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/log_writer.cc +1 -1
- package/deps/rocksdb/rocksdb/db/log_writer.h +1 -1
- package/deps/rocksdb/rocksdb/db/manual_compaction_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/memtable.cc +158 -56
- package/deps/rocksdb/rocksdb/db/memtable.h +2 -0
- package/deps/rocksdb/rocksdb/db/memtable_list_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/merge_helper_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/options_file_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/perf_context_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/periodic_task_scheduler_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/plain_table_db_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/prefix_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/range_del_aggregator.cc +52 -9
- package/deps/rocksdb/rocksdb/db/range_del_aggregator.h +31 -2
- package/deps/rocksdb/rocksdb/db/range_del_aggregator_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/range_tombstone_fragmenter.cc +81 -42
- package/deps/rocksdb/rocksdb/db/range_tombstone_fragmenter.h +78 -12
- package/deps/rocksdb/rocksdb/db/range_tombstone_fragmenter_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/repair_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/seqno_time_test.cc +154 -27
- package/deps/rocksdb/rocksdb/db/seqno_to_time_mapping.cc +21 -4
- package/deps/rocksdb/rocksdb/db/seqno_to_time_mapping.h +4 -1
- package/deps/rocksdb/rocksdb/db/table_cache.cc +18 -6
- package/deps/rocksdb/rocksdb/db/table_properties_collector_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/version_builder_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/version_edit_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/version_set.cc +15 -7
- package/deps/rocksdb/rocksdb/db/version_set.h +2 -1
- package/deps/rocksdb/rocksdb/db/version_set_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/version_util.h +3 -1
- package/deps/rocksdb/rocksdb/db/wal_manager_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/wide/wide_column_serialization.cc +28 -9
- package/deps/rocksdb/rocksdb/db/wide/wide_column_serialization.h +21 -0
- package/deps/rocksdb/rocksdb/db/wide/wide_column_serialization_test.cc +30 -0
- package/deps/rocksdb/rocksdb/db/wide/wide_columns.cc +4 -0
- package/deps/rocksdb/rocksdb/db/write_batch.cc +30 -7
- package/deps/rocksdb/rocksdb/db/write_batch_internal.h +24 -13
- package/deps/rocksdb/rocksdb/db/write_batch_test.cc +5 -4
- package/deps/rocksdb/rocksdb/db/write_callback_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/write_controller_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/batched_ops_stress.cc +104 -60
- package/deps/rocksdb/rocksdb/db_stress_tool/cf_consistency_stress.cc +199 -108
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.cc +39 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +8 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_driver.cc +3 -1
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +19 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_shared_state.h +26 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +247 -118
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.h +24 -4
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_tool.cc +18 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/expected_state.cc +129 -1
- package/deps/rocksdb/rocksdb/db_stress_tool/multi_ops_txns_stress.cc +22 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/multi_ops_txns_stress.h +4 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/no_batched_ops_stress.cc +312 -117
- package/deps/rocksdb/rocksdb/env/env_basic_test.cc +1 -0
- package/deps/rocksdb/rocksdb/env/fs_posix.cc +10 -2
- package/deps/rocksdb/rocksdb/env/io_posix_test.cc +1 -0
- package/deps/rocksdb/rocksdb/env/mock_env_test.cc +1 -0
- package/deps/rocksdb/rocksdb/file/delete_scheduler.cc +5 -1
- package/deps/rocksdb/rocksdb/file/delete_scheduler_test.cc +1 -0
- package/deps/rocksdb/rocksdb/file/prefetch_test.cc +1 -0
- package/deps/rocksdb/rocksdb/file/writable_file_writer.h +1 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/advanced_options.h +49 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/cache.h +44 -18
- package/deps/rocksdb/rocksdb/include/rocksdb/db.h +8 -7
- package/deps/rocksdb/rocksdb/include/rocksdb/file_system.h +6 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/listener.h +3 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/secondary_cache.h +17 -4
- package/deps/rocksdb/rocksdb/include/rocksdb/sst_file_reader.h +4 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/sst_file_writer.h +7 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/universal_compaction.h +1 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/wide_columns.h +9 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/write_batch.h +3 -6
- package/deps/rocksdb/rocksdb/logging/auto_roll_logger_test.cc +1 -0
- package/deps/rocksdb/rocksdb/logging/env_logger_test.cc +1 -0
- package/deps/rocksdb/rocksdb/logging/event_logger_test.cc +1 -0
- package/deps/rocksdb/rocksdb/memory/arena.cc +23 -88
- package/deps/rocksdb/rocksdb/memory/arena.h +25 -31
- package/deps/rocksdb/rocksdb/memory/arena_test.cc +61 -0
- package/deps/rocksdb/rocksdb/memory/memory_allocator_test.cc +1 -0
- package/deps/rocksdb/rocksdb/memtable/inlineskiplist_test.cc +1 -0
- package/deps/rocksdb/rocksdb/memtable/skiplist_test.cc +1 -0
- package/deps/rocksdb/rocksdb/memtable/write_buffer_manager_test.cc +1 -0
- package/deps/rocksdb/rocksdb/monitoring/histogram_test.cc +1 -0
- package/deps/rocksdb/rocksdb/monitoring/iostats_context_test.cc +1 -0
- package/deps/rocksdb/rocksdb/options/cf_options.cc +19 -0
- package/deps/rocksdb/rocksdb/options/cf_options.h +8 -0
- package/deps/rocksdb/rocksdb/options/configurable_test.cc +1 -0
- package/deps/rocksdb/rocksdb/options/options.cc +7 -0
- package/deps/rocksdb/rocksdb/options/options_helper.cc +6 -0
- package/deps/rocksdb/rocksdb/options/options_settable_test.cc +6 -0
- package/deps/rocksdb/rocksdb/options/options_test.cc +63 -40
- package/deps/rocksdb/rocksdb/port/mmap.cc +98 -0
- package/deps/rocksdb/rocksdb/port/mmap.h +70 -0
- package/deps/rocksdb/rocksdb/port/stack_trace.cc +7 -0
- package/deps/rocksdb/rocksdb/port/stack_trace.h +4 -1
- package/deps/rocksdb/rocksdb/port/win/port_win.h +2 -7
- package/deps/rocksdb/rocksdb/src.mk +1 -0
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_factory.cc +7 -7
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +3 -3
- package/deps/rocksdb/rocksdb/table/block_based/block_test.cc +1 -0
- package/deps/rocksdb/rocksdb/table/block_based/data_block_hash_index_test.cc +1 -0
- package/deps/rocksdb/rocksdb/table/block_based/full_filter_block_test.cc +1 -0
- package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block_test.cc +1 -0
- package/deps/rocksdb/rocksdb/table/cuckoo/cuckoo_table_builder_test.cc +1 -0
- package/deps/rocksdb/rocksdb/table/cuckoo/cuckoo_table_reader_test.cc +1 -0
- package/deps/rocksdb/rocksdb/table/get_context.cc +19 -1
- package/deps/rocksdb/rocksdb/table/get_context.h +9 -0
- package/deps/rocksdb/rocksdb/table/merger_test.cc +1 -0
- package/deps/rocksdb/rocksdb/table/merging_iterator.cc +10 -11
- package/deps/rocksdb/rocksdb/table/mock_table.cc +37 -19
- package/deps/rocksdb/rocksdb/table/mock_table.h +5 -1
- package/deps/rocksdb/rocksdb/table/sst_file_reader.cc +6 -0
- package/deps/rocksdb/rocksdb/table/sst_file_reader_test.cc +33 -0
- package/deps/rocksdb/rocksdb/table/sst_file_writer.cc +45 -6
- package/deps/rocksdb/rocksdb/test_util/testharness.h +2 -0
- package/deps/rocksdb/rocksdb/tools/block_cache_analyzer/block_cache_trace_analyzer_test.cc +1 -0
- package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +5 -0
- package/deps/rocksdb/rocksdb/tools/db_bench_tool_test.cc +1 -0
- package/deps/rocksdb/rocksdb/tools/io_tracer_parser_test.cc +1 -0
- package/deps/rocksdb/rocksdb/tools/ldb_cmd_test.cc +36 -0
- package/deps/rocksdb/rocksdb/tools/reduce_levels_test.cc +1 -0
- package/deps/rocksdb/rocksdb/tools/trace_analyzer_test.cc +1 -0
- package/deps/rocksdb/rocksdb/trace_replay/block_cache_tracer_test.cc +1 -0
- package/deps/rocksdb/rocksdb/trace_replay/io_tracer_test.cc +1 -0
- package/deps/rocksdb/rocksdb/util/autovector_test.cc +1 -0
- package/deps/rocksdb/rocksdb/util/bloom_test.cc +1 -0
- package/deps/rocksdb/rocksdb/util/coding_test.cc +1 -0
- package/deps/rocksdb/rocksdb/util/crc32c_test.cc +1 -0
- package/deps/rocksdb/rocksdb/util/dynamic_bloom_test.cc +1 -0
- package/deps/rocksdb/rocksdb/util/file_reader_writer_test.cc +1 -0
- package/deps/rocksdb/rocksdb/util/filelock_test.cc +1 -0
- package/deps/rocksdb/rocksdb/util/gflags_compat.h +12 -7
- package/deps/rocksdb/rocksdb/util/hash_test.cc +1 -0
- package/deps/rocksdb/rocksdb/util/heap_test.cc +4 -2
- package/deps/rocksdb/rocksdb/util/random_test.cc +1 -0
- package/deps/rocksdb/rocksdb/util/rate_limiter_test.cc +1 -0
- package/deps/rocksdb/rocksdb/util/repeatable_thread_test.cc +1 -0
- package/deps/rocksdb/rocksdb/util/ribbon_test.cc +1 -0
- package/deps/rocksdb/rocksdb/util/slice_transform_test.cc +1 -0
- package/deps/rocksdb/rocksdb/util/thread_list_test.cc +1 -0
- package/deps/rocksdb/rocksdb/util/thread_local_test.cc +1 -0
- package/deps/rocksdb/rocksdb/util/timer_test.cc +1 -0
- package/deps/rocksdb/rocksdb/util/work_queue_test.cc +4 -0
- package/deps/rocksdb/rocksdb/utilities/agg_merge/agg_merge_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/backup/backup_engine.cc +13 -0
- package/deps/rocksdb/rocksdb/utilities/backup/backup_engine_test.cc +9 -3
- package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/cassandra/cassandra_format_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/cassandra/cassandra_functional_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/cassandra/cassandra_row_merge_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/cassandra/cassandra_serialize_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/env_mirror_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/env_timed_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/fault_injection_secondary_cache.h +8 -0
- package/deps/rocksdb/rocksdb/utilities/memory/memory_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/object_registry_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/options/options_util_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/persistent_cache/hash_table_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/persistent_cache/persistent_cache_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/simulator_cache/cache_simulator_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/optimistic_transaction_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/timestamped_snapshot_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/transaction_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/write_committed_transaction_ts_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/write_unprepared_transaction_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/ttl/ttl_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/util_merge_operators_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/write_batch_with_index/write_batch_with_index.cc +7 -0
- package/deps/rocksdb/rocksdb/utilities/write_batch_with_index/write_batch_with_index_test.cc +20 -0
- package/index.js +12 -4
- package/package.json +1 -1
- package/prebuilds/darwin-arm64/node.napi.node +0 -0
- package/prebuilds/linux-x64/node.napi.node +0 -0
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
#include <cassert>
|
|
13
13
|
#include <functional>
|
|
14
14
|
|
|
15
|
+
#include "cache/cache_key.h"
|
|
15
16
|
#include "monitoring/perf_context_imp.h"
|
|
16
17
|
#include "monitoring/statistics.h"
|
|
17
18
|
#include "port/lang.h"
|
|
@@ -23,16 +24,28 @@ namespace ROCKSDB_NAMESPACE {
|
|
|
23
24
|
|
|
24
25
|
namespace hyper_clock_cache {
|
|
25
26
|
|
|
27
|
+
inline uint64_t GetRefcount(uint64_t meta) {
|
|
28
|
+
return ((meta >> ClockHandle::kAcquireCounterShift) -
|
|
29
|
+
(meta >> ClockHandle::kReleaseCounterShift)) &
|
|
30
|
+
ClockHandle::kCounterMask;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
void ClockHandleBasicData::FreeData() const {
|
|
34
|
+
if (deleter) {
|
|
35
|
+
UniqueId64x2 unhashed;
|
|
36
|
+
(*deleter)(ClockCacheShard::ReverseHash(hashed_key, &unhashed), value);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
26
40
|
static_assert(sizeof(ClockHandle) == 64U,
|
|
27
41
|
"Expecting size / alignment with common cache line size");
|
|
28
42
|
|
|
29
43
|
ClockHandleTable::ClockHandleTable(int hash_bits, bool initial_charge_metadata)
|
|
30
44
|
: length_bits_(hash_bits),
|
|
31
|
-
length_bits_mask_(
|
|
32
|
-
occupancy_limit_(static_cast<
|
|
33
|
-
|
|
45
|
+
length_bits_mask_((size_t{1} << length_bits_) - 1),
|
|
46
|
+
occupancy_limit_(static_cast<size_t>((uint64_t{1} << length_bits_) *
|
|
47
|
+
kStrictLoadFactor)),
|
|
34
48
|
array_(new ClockHandle[size_t{1} << length_bits_]) {
|
|
35
|
-
assert(hash_bits <= 32); // FIXME: ensure no overlap with sharding bits
|
|
36
49
|
if (initial_charge_metadata) {
|
|
37
50
|
usage_ += size_t{GetTableSize()} * sizeof(ClockHandle);
|
|
38
51
|
}
|
|
@@ -41,7 +54,7 @@ ClockHandleTable::ClockHandleTable(int hash_bits, bool initial_charge_metadata)
|
|
|
41
54
|
ClockHandleTable::~ClockHandleTable() {
|
|
42
55
|
// Assumes there are no references or active operations on any slot/element
|
|
43
56
|
// in the table.
|
|
44
|
-
for (
|
|
57
|
+
for (size_t i = 0; i < GetTableSize(); i++) {
|
|
45
58
|
ClockHandle& h = array_[i];
|
|
46
59
|
switch (h.meta >> ClockHandle::kStateShift) {
|
|
47
60
|
case ClockHandle::kStateEmpty:
|
|
@@ -49,9 +62,10 @@ ClockHandleTable::~ClockHandleTable() {
|
|
|
49
62
|
break;
|
|
50
63
|
case ClockHandle::kStateInvisible: // rare but possible
|
|
51
64
|
case ClockHandle::kStateVisible:
|
|
65
|
+
assert(GetRefcount(h.meta) == 0);
|
|
52
66
|
h.FreeData();
|
|
53
67
|
#ifndef NDEBUG
|
|
54
|
-
Rollback(h.
|
|
68
|
+
Rollback(h.hashed_key, &h);
|
|
55
69
|
usage_.fetch_sub(h.total_charge, std::memory_order_relaxed);
|
|
56
70
|
occupancy_.fetch_sub(1U, std::memory_order_relaxed);
|
|
57
71
|
#endif
|
|
@@ -64,7 +78,7 @@ ClockHandleTable::~ClockHandleTable() {
|
|
|
64
78
|
}
|
|
65
79
|
|
|
66
80
|
#ifndef NDEBUG
|
|
67
|
-
for (
|
|
81
|
+
for (size_t i = 0; i < GetTableSize(); i++) {
|
|
68
82
|
assert(array_[i].displacements.load() == 0);
|
|
69
83
|
}
|
|
70
84
|
#endif
|
|
@@ -147,12 +161,12 @@ inline void CorrectNearOverflow(uint64_t old_meta,
|
|
|
147
161
|
}
|
|
148
162
|
}
|
|
149
163
|
|
|
150
|
-
Status ClockHandleTable::Insert(const
|
|
164
|
+
Status ClockHandleTable::Insert(const ClockHandleBasicData& proto,
|
|
151
165
|
ClockHandle** handle, Cache::Priority priority,
|
|
152
166
|
size_t capacity, bool strict_capacity_limit) {
|
|
153
167
|
// Do we have the available occupancy? Optimistically assume we do
|
|
154
168
|
// and deal with it if we don't.
|
|
155
|
-
|
|
169
|
+
size_t old_occupancy = occupancy_.fetch_add(1, std::memory_order_acquire);
|
|
156
170
|
auto revert_occupancy_fn = [&]() {
|
|
157
171
|
occupancy_.fetch_sub(1, std::memory_order_relaxed);
|
|
158
172
|
};
|
|
@@ -191,7 +205,7 @@ Status ClockHandleTable::Insert(const ClockHandleMoreData& proto,
|
|
|
191
205
|
}
|
|
192
206
|
if (request_evict_charge > 0) {
|
|
193
207
|
size_t evicted_charge = 0;
|
|
194
|
-
|
|
208
|
+
size_t evicted_count = 0;
|
|
195
209
|
Evict(request_evict_charge, &evicted_charge, &evicted_count);
|
|
196
210
|
occupancy_.fetch_sub(evicted_count, std::memory_order_release);
|
|
197
211
|
if (LIKELY(evicted_charge > need_evict_charge)) {
|
|
@@ -256,7 +270,7 @@ Status ClockHandleTable::Insert(const ClockHandleMoreData& proto,
|
|
|
256
270
|
need_evict_charge = 1;
|
|
257
271
|
}
|
|
258
272
|
size_t evicted_charge = 0;
|
|
259
|
-
|
|
273
|
+
size_t evicted_count = 0;
|
|
260
274
|
if (need_evict_charge > 0) {
|
|
261
275
|
Evict(need_evict_charge, &evicted_charge, &evicted_count);
|
|
262
276
|
// Deal with potential occupancy deficit
|
|
@@ -316,9 +330,9 @@ Status ClockHandleTable::Insert(const ClockHandleMoreData& proto,
|
|
|
316
330
|
}
|
|
317
331
|
assert(initial_countdown > 0);
|
|
318
332
|
|
|
319
|
-
|
|
333
|
+
size_t probe = 0;
|
|
320
334
|
ClockHandle* e = FindSlot(
|
|
321
|
-
proto.
|
|
335
|
+
proto.hashed_key,
|
|
322
336
|
[&](ClockHandle* h) {
|
|
323
337
|
// Optimistically transition the slot from "empty" to
|
|
324
338
|
// "under construction" (no effect on other states)
|
|
@@ -331,7 +345,7 @@ Status ClockHandleTable::Insert(const ClockHandleMoreData& proto,
|
|
|
331
345
|
if (old_state == ClockHandle::kStateEmpty) {
|
|
332
346
|
// We've started inserting into an available slot, and taken
|
|
333
347
|
// ownership Save data fields
|
|
334
|
-
|
|
348
|
+
ClockHandleBasicData* h_alias = h;
|
|
335
349
|
*h_alias = proto;
|
|
336
350
|
|
|
337
351
|
// Transition from "under construction" state to "visible" state
|
|
@@ -368,7 +382,7 @@ Status ClockHandleTable::Insert(const ClockHandleMoreData& proto,
|
|
|
368
382
|
if ((old_meta >> ClockHandle::kStateShift) ==
|
|
369
383
|
ClockHandle::kStateVisible) {
|
|
370
384
|
// Acquired a read reference
|
|
371
|
-
if (h->
|
|
385
|
+
if (h->hashed_key == proto.hashed_key) {
|
|
372
386
|
// Match. Release in a way that boosts the clock state
|
|
373
387
|
old_meta = h->meta.fetch_add(
|
|
374
388
|
ClockHandle::kReleaseIncrement * initial_countdown,
|
|
@@ -424,7 +438,7 @@ Status ClockHandleTable::Insert(const ClockHandleMoreData& proto,
|
|
|
424
438
|
return Status::OK();
|
|
425
439
|
}
|
|
426
440
|
// Roll back table insertion
|
|
427
|
-
Rollback(proto.
|
|
441
|
+
Rollback(proto.hashed_key, e);
|
|
428
442
|
revert_occupancy_fn();
|
|
429
443
|
// Maybe fall back on detached insert
|
|
430
444
|
if (handle == nullptr) {
|
|
@@ -439,7 +453,7 @@ Status ClockHandleTable::Insert(const ClockHandleMoreData& proto,
|
|
|
439
453
|
assert(use_detached_insert);
|
|
440
454
|
|
|
441
455
|
ClockHandle* h = new ClockHandle();
|
|
442
|
-
|
|
456
|
+
ClockHandleBasicData* h_alias = h;
|
|
443
457
|
*h_alias = proto;
|
|
444
458
|
h->detached = true;
|
|
445
459
|
// Single reference (detached entries only created if returning a refed
|
|
@@ -460,10 +474,10 @@ Status ClockHandleTable::Insert(const ClockHandleMoreData& proto,
|
|
|
460
474
|
return Status::OkOverwritten();
|
|
461
475
|
}
|
|
462
476
|
|
|
463
|
-
ClockHandle* ClockHandleTable::Lookup(const
|
|
464
|
-
|
|
477
|
+
ClockHandle* ClockHandleTable::Lookup(const UniqueId64x2& hashed_key) {
|
|
478
|
+
size_t probe = 0;
|
|
465
479
|
ClockHandle* e = FindSlot(
|
|
466
|
-
|
|
480
|
+
hashed_key,
|
|
467
481
|
[&](ClockHandle* h) {
|
|
468
482
|
// Mostly branch-free version (similar performance)
|
|
469
483
|
/*
|
|
@@ -494,7 +508,7 @@ ClockHandle* ClockHandleTable::Lookup(const CacheKeyBytes& key, uint32_t hash) {
|
|
|
494
508
|
if ((old_meta >> ClockHandle::kStateShift) ==
|
|
495
509
|
ClockHandle::kStateVisible) {
|
|
496
510
|
// Acquired a read reference
|
|
497
|
-
if (h->
|
|
511
|
+
if (h->hashed_key == hashed_key) {
|
|
498
512
|
// Match
|
|
499
513
|
return true;
|
|
500
514
|
} else {
|
|
@@ -562,10 +576,7 @@ bool ClockHandleTable::Release(ClockHandle* h, bool useful,
|
|
|
562
576
|
}
|
|
563
577
|
// Take ownership if no refs
|
|
564
578
|
do {
|
|
565
|
-
|
|
566
|
-
(old_meta >> ClockHandle::kReleaseCounterShift)) &
|
|
567
|
-
ClockHandle::kCounterMask;
|
|
568
|
-
if (refcount != 0) {
|
|
579
|
+
if (GetRefcount(old_meta) != 0) {
|
|
569
580
|
// Not last ref at some point in time during this Release call
|
|
570
581
|
// Correct for possible (but rare) overflow
|
|
571
582
|
CorrectNearOverflow(old_meta, h->meta);
|
|
@@ -592,7 +603,7 @@ bool ClockHandleTable::Release(ClockHandle* h, bool useful,
|
|
|
592
603
|
delete h;
|
|
593
604
|
detached_usage_.fetch_sub(total_charge, std::memory_order_relaxed);
|
|
594
605
|
} else {
|
|
595
|
-
|
|
606
|
+
UniqueId64x2 hashed_key = h->hashed_key;
|
|
596
607
|
#ifndef NDEBUG
|
|
597
608
|
// Mark slot as empty, with assertion
|
|
598
609
|
old_meta = h->meta.exchange(0, std::memory_order_release);
|
|
@@ -603,7 +614,7 @@ bool ClockHandleTable::Release(ClockHandle* h, bool useful,
|
|
|
603
614
|
h->meta.store(0, std::memory_order_release);
|
|
604
615
|
#endif
|
|
605
616
|
occupancy_.fetch_sub(1U, std::memory_order_release);
|
|
606
|
-
Rollback(
|
|
617
|
+
Rollback(hashed_key, h);
|
|
607
618
|
}
|
|
608
619
|
usage_.fetch_sub(total_charge, std::memory_order_relaxed);
|
|
609
620
|
assert(usage_.load(std::memory_order_relaxed) < SIZE_MAX / 2);
|
|
@@ -622,6 +633,8 @@ void ClockHandleTable::Ref(ClockHandle& h) {
|
|
|
622
633
|
|
|
623
634
|
assert((old_meta >> ClockHandle::kStateShift) &
|
|
624
635
|
ClockHandle::kStateShareableBit);
|
|
636
|
+
// Must have already had a reference
|
|
637
|
+
assert(GetRefcount(old_meta) > 0);
|
|
625
638
|
(void)old_meta;
|
|
626
639
|
}
|
|
627
640
|
|
|
@@ -648,10 +661,10 @@ void ClockHandleTable::TEST_ReleaseN(ClockHandle* h, size_t n) {
|
|
|
648
661
|
}
|
|
649
662
|
}
|
|
650
663
|
|
|
651
|
-
void ClockHandleTable::Erase(const
|
|
652
|
-
|
|
664
|
+
void ClockHandleTable::Erase(const UniqueId64x2& hashed_key) {
|
|
665
|
+
size_t probe = 0;
|
|
653
666
|
(void)FindSlot(
|
|
654
|
-
|
|
667
|
+
hashed_key,
|
|
655
668
|
[&](ClockHandle* h) {
|
|
656
669
|
// Could be multiple entries in rare cases. Erase them all.
|
|
657
670
|
// Optimistically increment acquire counter
|
|
@@ -661,7 +674,7 @@ void ClockHandleTable::Erase(const CacheKeyBytes& key, uint32_t hash) {
|
|
|
661
674
|
if ((old_meta >> ClockHandle::kStateShift) ==
|
|
662
675
|
ClockHandle::kStateVisible) {
|
|
663
676
|
// Acquired a read reference
|
|
664
|
-
if (h->
|
|
677
|
+
if (h->hashed_key == hashed_key) {
|
|
665
678
|
// Match. Set invisible.
|
|
666
679
|
old_meta =
|
|
667
680
|
h->meta.fetch_and(~(uint64_t{ClockHandle::kStateVisibleBit}
|
|
@@ -671,10 +684,7 @@ void ClockHandleTable::Erase(const CacheKeyBytes& key, uint32_t hash) {
|
|
|
671
684
|
old_meta &= ~(uint64_t{ClockHandle::kStateVisibleBit}
|
|
672
685
|
<< ClockHandle::kStateShift);
|
|
673
686
|
for (;;) {
|
|
674
|
-
uint64_t refcount =
|
|
675
|
-
((old_meta >> ClockHandle::kAcquireCounterShift) -
|
|
676
|
-
(old_meta >> ClockHandle::kReleaseCounterShift)) &
|
|
677
|
-
ClockHandle::kCounterMask;
|
|
687
|
+
uint64_t refcount = GetRefcount(old_meta);
|
|
678
688
|
assert(refcount > 0);
|
|
679
689
|
if (refcount > 1) {
|
|
680
690
|
// Not last ref at some point in time during this Erase call
|
|
@@ -683,10 +693,12 @@ void ClockHandleTable::Erase(const CacheKeyBytes& key, uint32_t hash) {
|
|
|
683
693
|
std::memory_order_release);
|
|
684
694
|
break;
|
|
685
695
|
} else if (h->meta.compare_exchange_weak(
|
|
686
|
-
old_meta,
|
|
687
|
-
|
|
696
|
+
old_meta,
|
|
697
|
+
uint64_t{ClockHandle::kStateConstruction}
|
|
698
|
+
<< ClockHandle::kStateShift,
|
|
699
|
+
std::memory_order_acq_rel)) {
|
|
688
700
|
// Took ownership
|
|
689
|
-
assert(
|
|
701
|
+
assert(hashed_key == h->hashed_key);
|
|
690
702
|
// TODO? Delay freeing?
|
|
691
703
|
h->FreeData();
|
|
692
704
|
usage_.fetch_sub(h->total_charge, std::memory_order_relaxed);
|
|
@@ -701,7 +713,7 @@ void ClockHandleTable::Erase(const CacheKeyBytes& key, uint32_t hash) {
|
|
|
701
713
|
h->meta.store(0, std::memory_order_release);
|
|
702
714
|
#endif
|
|
703
715
|
occupancy_.fetch_sub(1U, std::memory_order_release);
|
|
704
|
-
Rollback(
|
|
716
|
+
Rollback(hashed_key, h);
|
|
705
717
|
break;
|
|
706
718
|
}
|
|
707
719
|
}
|
|
@@ -730,51 +742,60 @@ void ClockHandleTable::Erase(const CacheKeyBytes& key, uint32_t hash) {
|
|
|
730
742
|
}
|
|
731
743
|
|
|
732
744
|
void ClockHandleTable::ConstApplyToEntriesRange(
|
|
733
|
-
std::function<void(const ClockHandle&)> func,
|
|
734
|
-
|
|
745
|
+
std::function<void(const ClockHandle&)> func, size_t index_begin,
|
|
746
|
+
size_t index_end, bool apply_if_will_be_deleted) const {
|
|
735
747
|
uint64_t check_state_mask = ClockHandle::kStateShareableBit;
|
|
736
748
|
if (!apply_if_will_be_deleted) {
|
|
737
749
|
check_state_mask |= ClockHandle::kStateVisibleBit;
|
|
738
750
|
}
|
|
739
751
|
|
|
740
|
-
for (
|
|
752
|
+
for (size_t i = index_begin; i < index_end; i++) {
|
|
741
753
|
ClockHandle& h = array_[i];
|
|
742
754
|
|
|
755
|
+
// Note: to avoid using compare_exchange, we have to be extra careful.
|
|
743
756
|
uint64_t old_meta = h.meta.load(std::memory_order_relaxed);
|
|
744
757
|
// Check if it's an entry visible to lookups
|
|
745
758
|
if ((old_meta >> ClockHandle::kStateShift) & check_state_mask) {
|
|
746
|
-
// Increment acquire counter
|
|
759
|
+
// Increment acquire counter. Note: it's possible that the entry has
|
|
760
|
+
// completely changed since we loaded old_meta, but incrementing acquire
|
|
761
|
+
// count is always safe. (Similar to optimistic Lookup here.)
|
|
747
762
|
old_meta = h.meta.fetch_add(ClockHandle::kAcquireIncrement,
|
|
748
763
|
std::memory_order_acquire);
|
|
749
|
-
//
|
|
750
|
-
if ((old_meta >> ClockHandle::kStateShift) &
|
|
751
|
-
|
|
764
|
+
// Check whether we actually acquired a reference.
|
|
765
|
+
if ((old_meta >> ClockHandle::kStateShift) &
|
|
766
|
+
ClockHandle::kStateShareableBit) {
|
|
767
|
+
// Apply func if appropriate
|
|
768
|
+
if ((old_meta >> ClockHandle::kStateShift) & check_state_mask) {
|
|
769
|
+
func(h);
|
|
770
|
+
}
|
|
771
|
+
// Pretend we never took the reference
|
|
772
|
+
h.meta.fetch_sub(ClockHandle::kAcquireIncrement,
|
|
773
|
+
std::memory_order_release);
|
|
774
|
+
// No net change, so don't need to check for overflow
|
|
775
|
+
} else {
|
|
776
|
+
// For other states, incrementing the acquire counter has no effect
|
|
777
|
+
// so we don't need to undo it. Furthermore, we cannot safely undo
|
|
778
|
+
// it because we did not acquire a read reference to lock the
|
|
779
|
+
// entry in a Shareable state.
|
|
752
780
|
}
|
|
753
|
-
// Pretend we never took the reference
|
|
754
|
-
h.meta.fetch_sub(ClockHandle::kAcquireIncrement,
|
|
755
|
-
std::memory_order_release);
|
|
756
|
-
// No net change, so don't need to check for overflow
|
|
757
781
|
}
|
|
758
782
|
}
|
|
759
783
|
}
|
|
760
784
|
|
|
761
785
|
void ClockHandleTable::EraseUnRefEntries() {
|
|
762
|
-
for (
|
|
786
|
+
for (size_t i = 0; i <= this->length_bits_mask_; i++) {
|
|
763
787
|
ClockHandle& h = array_[i];
|
|
764
788
|
|
|
765
789
|
uint64_t old_meta = h.meta.load(std::memory_order_relaxed);
|
|
766
|
-
uint64_t refcount = ((old_meta >> ClockHandle::kAcquireCounterShift) -
|
|
767
|
-
(old_meta >> ClockHandle::kReleaseCounterShift)) &
|
|
768
|
-
ClockHandle::kCounterMask;
|
|
769
790
|
if (old_meta & (uint64_t{ClockHandle::kStateShareableBit}
|
|
770
791
|
<< ClockHandle::kStateShift) &&
|
|
771
|
-
|
|
792
|
+
GetRefcount(old_meta) == 0 &&
|
|
772
793
|
h.meta.compare_exchange_strong(old_meta,
|
|
773
794
|
uint64_t{ClockHandle::kStateConstruction}
|
|
774
795
|
<< ClockHandle::kStateShift,
|
|
775
796
|
std::memory_order_acquire)) {
|
|
776
797
|
// Took ownership
|
|
777
|
-
|
|
798
|
+
UniqueId64x2 hashed_key = h.hashed_key;
|
|
778
799
|
h.FreeData();
|
|
779
800
|
usage_.fetch_sub(h.total_charge, std::memory_order_relaxed);
|
|
780
801
|
#ifndef NDEBUG
|
|
@@ -787,37 +808,29 @@ void ClockHandleTable::EraseUnRefEntries() {
|
|
|
787
808
|
h.meta.store(0, std::memory_order_release);
|
|
788
809
|
#endif
|
|
789
810
|
occupancy_.fetch_sub(1U, std::memory_order_release);
|
|
790
|
-
Rollback(
|
|
811
|
+
Rollback(hashed_key, &h);
|
|
791
812
|
}
|
|
792
813
|
}
|
|
793
814
|
}
|
|
794
815
|
|
|
795
|
-
namespace {
|
|
796
|
-
inline uint32_t Remix1(uint32_t hash) {
|
|
797
|
-
return Lower32of64((uint64_t{hash} * 0xbc9f1d35) >> 29);
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
inline uint32_t Remix2(uint32_t hash) {
|
|
801
|
-
return Lower32of64((uint64_t{hash} * 0x7a2bb9d5) >> 29);
|
|
802
|
-
}
|
|
803
|
-
} // namespace
|
|
804
|
-
|
|
805
816
|
ClockHandle* ClockHandleTable::FindSlot(
|
|
806
|
-
|
|
817
|
+
const UniqueId64x2& hashed_key, std::function<bool(ClockHandle*)> match_fn,
|
|
807
818
|
std::function<bool(ClockHandle*)> abort_fn,
|
|
808
|
-
std::function<void(ClockHandle*)> update_fn,
|
|
819
|
+
std::function<void(ClockHandle*)> update_fn, size_t& probe) {
|
|
820
|
+
// NOTE: upper 32 bits of hashed_key[0] is used for sharding
|
|
821
|
+
//
|
|
809
822
|
// We use double-hashing probing. Every probe in the sequence is a
|
|
810
823
|
// pseudorandom integer, computed as a linear function of two random hashes,
|
|
811
824
|
// which we call base and increment. Specifically, the i-th probe is base + i
|
|
812
825
|
// * increment modulo the table size.
|
|
813
|
-
|
|
826
|
+
size_t base = static_cast<size_t>(hashed_key[1]);
|
|
814
827
|
// We use an odd increment, which is relatively prime with the power-of-two
|
|
815
828
|
// table size. This implies that we cycle back to the first probe only
|
|
816
829
|
// after probing every slot exactly once.
|
|
817
830
|
// TODO: we could also reconsider linear probing, though locality benefits
|
|
818
831
|
// are limited because each slot is a full cache line
|
|
819
|
-
|
|
820
|
-
|
|
832
|
+
size_t increment = static_cast<size_t>(hashed_key[0]) | 1U;
|
|
833
|
+
size_t current = ModTableSize(base + probe * increment);
|
|
821
834
|
while (probe <= length_bits_mask_) {
|
|
822
835
|
ClockHandle* h = &array_[current];
|
|
823
836
|
if (match_fn(h)) {
|
|
@@ -835,22 +848,23 @@ ClockHandle* ClockHandleTable::FindSlot(
|
|
|
835
848
|
return nullptr;
|
|
836
849
|
}
|
|
837
850
|
|
|
838
|
-
void ClockHandleTable::Rollback(
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
851
|
+
void ClockHandleTable::Rollback(const UniqueId64x2& hashed_key,
|
|
852
|
+
const ClockHandle* h) {
|
|
853
|
+
size_t current = ModTableSize(hashed_key[1]);
|
|
854
|
+
size_t increment = static_cast<size_t>(hashed_key[0]) | 1U;
|
|
855
|
+
for (size_t i = 0; &array_[current] != h; i++) {
|
|
842
856
|
array_[current].displacements.fetch_sub(1, std::memory_order_relaxed);
|
|
843
857
|
current = ModTableSize(current + increment);
|
|
844
858
|
}
|
|
845
859
|
}
|
|
846
860
|
|
|
847
861
|
void ClockHandleTable::Evict(size_t requested_charge, size_t* freed_charge,
|
|
848
|
-
|
|
862
|
+
size_t* freed_count) {
|
|
849
863
|
// precondition
|
|
850
864
|
assert(requested_charge > 0);
|
|
851
865
|
|
|
852
866
|
// TODO: make a tuning parameter?
|
|
853
|
-
constexpr
|
|
867
|
+
constexpr size_t step_size = 4;
|
|
854
868
|
|
|
855
869
|
// First (concurrent) increment clock pointer
|
|
856
870
|
uint64_t old_clock_pointer =
|
|
@@ -865,7 +879,7 @@ void ClockHandleTable::Evict(size_t requested_charge, size_t* freed_charge,
|
|
|
865
879
|
old_clock_pointer + (ClockHandle::kMaxCountdown << length_bits_);
|
|
866
880
|
|
|
867
881
|
for (;;) {
|
|
868
|
-
for (
|
|
882
|
+
for (size_t i = 0; i < step_size; i++) {
|
|
869
883
|
ClockHandle& h = array_[ModTableSize(Lower32of64(old_clock_pointer + i))];
|
|
870
884
|
uint64_t meta = h.meta.load(std::memory_order_relaxed);
|
|
871
885
|
|
|
@@ -877,13 +891,12 @@ void ClockHandleTable::Evict(size_t requested_charge, size_t* freed_charge,
|
|
|
877
891
|
// Only clock update entries with no outstanding refs
|
|
878
892
|
continue;
|
|
879
893
|
}
|
|
880
|
-
if (!(meta >> ClockHandle::kStateShift &
|
|
894
|
+
if (!((meta >> ClockHandle::kStateShift) &
|
|
881
895
|
ClockHandle::kStateShareableBit)) {
|
|
882
896
|
// Only clock update Shareable entries
|
|
883
897
|
continue;
|
|
884
898
|
}
|
|
885
|
-
|
|
886
|
-
if (meta >> ClockHandle::kStateShift == ClockHandle::kStateVisible &&
|
|
899
|
+
if ((meta >> ClockHandle::kStateShift == ClockHandle::kStateVisible) &&
|
|
887
900
|
acquire_count > 0) {
|
|
888
901
|
// Decrement clock
|
|
889
902
|
uint64_t new_count = std::min(acquire_count - 1,
|
|
@@ -907,7 +920,7 @@ void ClockHandleTable::Evict(size_t requested_charge, size_t* freed_charge,
|
|
|
907
920
|
<< ClockHandle::kStateShift,
|
|
908
921
|
std::memory_order_acquire)) {
|
|
909
922
|
// Took ownership
|
|
910
|
-
|
|
923
|
+
const UniqueId64x2& hashed_key = h.hashed_key;
|
|
911
924
|
// TODO? Delay freeing?
|
|
912
925
|
h.FreeData();
|
|
913
926
|
*freed_charge += h.total_charge;
|
|
@@ -921,7 +934,7 @@ void ClockHandleTable::Evict(size_t requested_charge, size_t* freed_charge,
|
|
|
921
934
|
h.meta.store(0, std::memory_order_release);
|
|
922
935
|
#endif
|
|
923
936
|
*freed_count += 1;
|
|
924
|
-
Rollback(
|
|
937
|
+
Rollback(hashed_key, &h);
|
|
925
938
|
}
|
|
926
939
|
}
|
|
927
940
|
|
|
@@ -942,7 +955,7 @@ void ClockHandleTable::Evict(size_t requested_charge, size_t* freed_charge,
|
|
|
942
955
|
ClockCacheShard::ClockCacheShard(
|
|
943
956
|
size_t capacity, size_t estimated_value_size, bool strict_capacity_limit,
|
|
944
957
|
CacheMetadataChargePolicy metadata_charge_policy)
|
|
945
|
-
:
|
|
958
|
+
: CacheShardBase(metadata_charge_policy),
|
|
946
959
|
table_(
|
|
947
960
|
CalcHashBits(capacity, estimated_value_size, metadata_charge_policy),
|
|
948
961
|
/*initial_charge_metadata*/ metadata_charge_policy ==
|
|
@@ -958,31 +971,33 @@ void ClockCacheShard::EraseUnRefEntries() { table_.EraseUnRefEntries(); }
|
|
|
958
971
|
void ClockCacheShard::ApplyToSomeEntries(
|
|
959
972
|
const std::function<void(const Slice& key, void* value, size_t charge,
|
|
960
973
|
DeleterFn deleter)>& callback,
|
|
961
|
-
|
|
974
|
+
size_t average_entries_per_lock, size_t* state) {
|
|
962
975
|
// The state is essentially going to be the starting hash, which works
|
|
963
976
|
// nicely even if we resize between calls because we use upper-most
|
|
964
977
|
// hash bits for table indexes.
|
|
965
|
-
|
|
966
|
-
|
|
978
|
+
size_t length_bits = table_.GetLengthBits();
|
|
979
|
+
size_t length = table_.GetTableSize();
|
|
967
980
|
|
|
968
981
|
assert(average_entries_per_lock > 0);
|
|
969
982
|
// Assuming we are called with same average_entries_per_lock repeatedly,
|
|
970
983
|
// this simplifies some logic (index_end will not overflow).
|
|
971
984
|
assert(average_entries_per_lock < length || *state == 0);
|
|
972
985
|
|
|
973
|
-
|
|
974
|
-
|
|
986
|
+
size_t index_begin = *state >> (sizeof(size_t) * 8u - length_bits);
|
|
987
|
+
size_t index_end = index_begin + average_entries_per_lock;
|
|
975
988
|
if (index_end >= length) {
|
|
976
989
|
// Going to end.
|
|
977
990
|
index_end = length;
|
|
978
|
-
*state =
|
|
991
|
+
*state = SIZE_MAX;
|
|
979
992
|
} else {
|
|
980
|
-
*state = index_end << (
|
|
993
|
+
*state = index_end << (sizeof(size_t) * 8u - length_bits);
|
|
981
994
|
}
|
|
982
995
|
|
|
983
996
|
table_.ConstApplyToEntriesRange(
|
|
984
997
|
[callback](const ClockHandle& h) {
|
|
985
|
-
|
|
998
|
+
UniqueId64x2 unhashed;
|
|
999
|
+
callback(ReverseHash(h.hashed_key, &unhashed), h.value, h.total_charge,
|
|
1000
|
+
h.deleter);
|
|
986
1001
|
},
|
|
987
1002
|
index_begin, index_end, false);
|
|
988
1003
|
}
|
|
@@ -998,7 +1013,7 @@ int ClockCacheShard::CalcHashBits(
|
|
|
998
1013
|
uint64_t num_slots =
|
|
999
1014
|
static_cast<uint64_t>(capacity / average_slot_charge + 0.999999);
|
|
1000
1015
|
|
|
1001
|
-
int hash_bits =
|
|
1016
|
+
int hash_bits = FloorLog2((num_slots << 1) - 1);
|
|
1002
1017
|
if (metadata_charge_policy == kFullChargeCacheMetadata) {
|
|
1003
1018
|
// For very small estimated value sizes, it's possible to overshoot
|
|
1004
1019
|
while (hash_bits > 0 &&
|
|
@@ -1020,17 +1035,16 @@ void ClockCacheShard::SetStrictCapacityLimit(bool strict_capacity_limit) {
|
|
|
1020
1035
|
// next Insert will take care of any necessary evictions
|
|
1021
1036
|
}
|
|
1022
1037
|
|
|
1023
|
-
Status ClockCacheShard::Insert(const Slice& key,
|
|
1024
|
-
|
|
1025
|
-
Cache::
|
|
1038
|
+
Status ClockCacheShard::Insert(const Slice& key, const UniqueId64x2& hashed_key,
|
|
1039
|
+
void* value, size_t charge,
|
|
1040
|
+
Cache::DeleterFn deleter, ClockHandle** handle,
|
|
1026
1041
|
Cache::Priority priority) {
|
|
1027
1042
|
if (UNLIKELY(key.size() != kCacheKeySize)) {
|
|
1028
1043
|
return Status::NotSupported("ClockCache only supports key size " +
|
|
1029
1044
|
std::to_string(kCacheKeySize) + "B");
|
|
1030
1045
|
}
|
|
1031
|
-
|
|
1032
|
-
proto.
|
|
1033
|
-
proto.hash = hash;
|
|
1046
|
+
ClockHandleBasicData proto;
|
|
1047
|
+
proto.hashed_key = hashed_key;
|
|
1034
1048
|
proto.value = value;
|
|
1035
1049
|
proto.deleter = deleter;
|
|
1036
1050
|
proto.total_charge = charge;
|
|
@@ -1041,49 +1055,47 @@ Status ClockCacheShard::Insert(const Slice& key, uint32_t hash, void* value,
|
|
|
1041
1055
|
return s;
|
|
1042
1056
|
}
|
|
1043
1057
|
|
|
1044
|
-
|
|
1058
|
+
ClockHandle* ClockCacheShard::Lookup(const Slice& key,
|
|
1059
|
+
const UniqueId64x2& hashed_key) {
|
|
1045
1060
|
if (UNLIKELY(key.size() != kCacheKeySize)) {
|
|
1046
1061
|
return nullptr;
|
|
1047
1062
|
}
|
|
1048
|
-
|
|
1049
|
-
return reinterpret_cast<Cache::Handle*>(table_.Lookup(*key_bytes, hash));
|
|
1063
|
+
return table_.Lookup(hashed_key);
|
|
1050
1064
|
}
|
|
1051
1065
|
|
|
1052
|
-
bool ClockCacheShard::Ref(
|
|
1066
|
+
bool ClockCacheShard::Ref(ClockHandle* h) {
|
|
1053
1067
|
if (h == nullptr) {
|
|
1054
1068
|
return false;
|
|
1055
1069
|
}
|
|
1056
|
-
table_.Ref(*
|
|
1070
|
+
table_.Ref(*h);
|
|
1057
1071
|
return true;
|
|
1058
1072
|
}
|
|
1059
1073
|
|
|
1060
|
-
bool ClockCacheShard::Release(
|
|
1074
|
+
bool ClockCacheShard::Release(ClockHandle* handle, bool useful,
|
|
1061
1075
|
bool erase_if_last_ref) {
|
|
1062
1076
|
if (handle == nullptr) {
|
|
1063
1077
|
return false;
|
|
1064
1078
|
}
|
|
1065
|
-
return table_.Release(
|
|
1066
|
-
erase_if_last_ref);
|
|
1079
|
+
return table_.Release(handle, useful, erase_if_last_ref);
|
|
1067
1080
|
}
|
|
1068
1081
|
|
|
1069
|
-
void ClockCacheShard::TEST_RefN(
|
|
1070
|
-
table_.TEST_RefN(*
|
|
1082
|
+
void ClockCacheShard::TEST_RefN(ClockHandle* h, size_t n) {
|
|
1083
|
+
table_.TEST_RefN(*h, n);
|
|
1071
1084
|
}
|
|
1072
1085
|
|
|
1073
|
-
void ClockCacheShard::TEST_ReleaseN(
|
|
1074
|
-
table_.TEST_ReleaseN(
|
|
1086
|
+
void ClockCacheShard::TEST_ReleaseN(ClockHandle* h, size_t n) {
|
|
1087
|
+
table_.TEST_ReleaseN(h, n);
|
|
1075
1088
|
}
|
|
1076
1089
|
|
|
1077
|
-
bool ClockCacheShard::Release(
|
|
1090
|
+
bool ClockCacheShard::Release(ClockHandle* handle, bool erase_if_last_ref) {
|
|
1078
1091
|
return Release(handle, /*useful=*/true, erase_if_last_ref);
|
|
1079
1092
|
}
|
|
1080
1093
|
|
|
1081
|
-
void ClockCacheShard::Erase(const Slice& key,
|
|
1094
|
+
void ClockCacheShard::Erase(const Slice& key, const UniqueId64x2& hashed_key) {
|
|
1082
1095
|
if (UNLIKELY(key.size() != kCacheKeySize)) {
|
|
1083
1096
|
return;
|
|
1084
1097
|
}
|
|
1085
|
-
|
|
1086
|
-
table_.Erase(*key_bytes, hash);
|
|
1098
|
+
table_.Erase(hashed_key);
|
|
1087
1099
|
}
|
|
1088
1100
|
|
|
1089
1101
|
size_t ClockCacheShard::GetUsage() const { return table_.GetUsage(); }
|
|
@@ -1101,9 +1113,7 @@ size_t ClockCacheShard::GetPinnedUsage() const {
|
|
|
1101
1113
|
table_.ConstApplyToEntriesRange(
|
|
1102
1114
|
[&table_pinned_usage, charge_metadata](const ClockHandle& h) {
|
|
1103
1115
|
uint64_t meta = h.meta.load(std::memory_order_relaxed);
|
|
1104
|
-
uint64_t refcount = (
|
|
1105
|
-
(meta >> ClockHandle::kReleaseCounterShift)) &
|
|
1106
|
-
ClockHandle::kCounterMask;
|
|
1116
|
+
uint64_t refcount = GetRefcount(meta);
|
|
1107
1117
|
// Holding one ref for ConstApplyToEntriesRange
|
|
1108
1118
|
assert(refcount > 0);
|
|
1109
1119
|
if (refcount > 1) {
|
|
@@ -1129,39 +1139,19 @@ size_t ClockCacheShard::GetTableAddressCount() const {
|
|
|
1129
1139
|
HyperClockCache::HyperClockCache(
|
|
1130
1140
|
size_t capacity, size_t estimated_value_size, int num_shard_bits,
|
|
1131
1141
|
bool strict_capacity_limit,
|
|
1132
|
-
CacheMetadataChargePolicy metadata_charge_policy
|
|
1133
|
-
|
|
1134
|
-
|
|
1142
|
+
CacheMetadataChargePolicy metadata_charge_policy,
|
|
1143
|
+
std::shared_ptr<MemoryAllocator> memory_allocator)
|
|
1144
|
+
: ShardedCache(capacity, num_shard_bits, strict_capacity_limit,
|
|
1145
|
+
std::move(memory_allocator)) {
|
|
1135
1146
|
assert(estimated_value_size > 0 ||
|
|
1136
1147
|
metadata_charge_policy != kDontChargeCacheMetadata);
|
|
1137
1148
|
// TODO: should not need to go through two levels of pointer indirection to
|
|
1138
1149
|
// get to table entries
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
ClockCacheShard(per_shard, estimated_value_size, strict_capacity_limit,
|
|
1145
|
-
metadata_charge_policy);
|
|
1146
|
-
}
|
|
1147
|
-
}
|
|
1148
|
-
|
|
1149
|
-
HyperClockCache::~HyperClockCache() {
|
|
1150
|
-
if (shards_ != nullptr) {
|
|
1151
|
-
assert(num_shards_ > 0);
|
|
1152
|
-
for (int i = 0; i < num_shards_; i++) {
|
|
1153
|
-
shards_[i].~ClockCacheShard();
|
|
1154
|
-
}
|
|
1155
|
-
port::cacheline_aligned_free(shards_);
|
|
1156
|
-
}
|
|
1157
|
-
}
|
|
1158
|
-
|
|
1159
|
-
CacheShard* HyperClockCache::GetShard(uint32_t shard) {
|
|
1160
|
-
return reinterpret_cast<CacheShard*>(&shards_[shard]);
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
|
-
const CacheShard* HyperClockCache::GetShard(uint32_t shard) const {
|
|
1164
|
-
return reinterpret_cast<CacheShard*>(&shards_[shard]);
|
|
1150
|
+
size_t per_shard = GetPerShardCapacity();
|
|
1151
|
+
InitShards([=](ClockCacheShard* cs) {
|
|
1152
|
+
new (cs) ClockCacheShard(per_shard, estimated_value_size,
|
|
1153
|
+
strict_capacity_limit, metadata_charge_policy);
|
|
1154
|
+
});
|
|
1165
1155
|
}
|
|
1166
1156
|
|
|
1167
1157
|
void* HyperClockCache::Value(Handle* handle) {
|
|
@@ -1177,18 +1167,6 @@ Cache::DeleterFn HyperClockCache::GetDeleter(Handle* handle) const {
|
|
|
1177
1167
|
return h->deleter;
|
|
1178
1168
|
}
|
|
1179
1169
|
|
|
1180
|
-
uint32_t HyperClockCache::GetHash(Handle* handle) const {
|
|
1181
|
-
return reinterpret_cast<const ClockHandle*>(handle)->hash;
|
|
1182
|
-
}
|
|
1183
|
-
|
|
1184
|
-
void HyperClockCache::DisownData() {
|
|
1185
|
-
// Leak data only if that won't generate an ASAN/valgrind warning.
|
|
1186
|
-
if (!kMustFreeHeapAllocations) {
|
|
1187
|
-
shards_ = nullptr;
|
|
1188
|
-
num_shards_ = 0;
|
|
1189
|
-
}
|
|
1190
|
-
}
|
|
1191
|
-
|
|
1192
1170
|
} // namespace hyper_clock_cache
|
|
1193
1171
|
|
|
1194
1172
|
// DEPRECATED (see public API)
|
|
@@ -1214,7 +1192,7 @@ std::shared_ptr<Cache> HyperClockCacheOptions::MakeSharedCache() const {
|
|
|
1214
1192
|
}
|
|
1215
1193
|
return std::make_shared<hyper_clock_cache::HyperClockCache>(
|
|
1216
1194
|
capacity, estimated_entry_charge, my_num_shard_bits,
|
|
1217
|
-
strict_capacity_limit, metadata_charge_policy);
|
|
1195
|
+
strict_capacity_limit, metadata_charge_policy, memory_allocator);
|
|
1218
1196
|
}
|
|
1219
1197
|
|
|
1220
1198
|
} // namespace ROCKSDB_NAMESPACE
|