diff --git a/HISTORY.md b/HISTORY.md index a72d8caec7..65c4c8242e 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -4,7 +4,7 @@ * Fix RepeatableThread to work properly with on thread start callback feature (https://github.com/speedb-io/speedb/pull/667). -### New Features +### New Features * Non-Blocking Manual Compaction (CompactRange()) - Support non-blocking manual compactions by setting a new CompactRangeOptions option (async_completion_cb). When set, the CompactRange() call will return control to the caller immediately. The manual compaction iteslf will be performed in an internally created thread. The manual compaction will ALWAYS call the specified callback upon completion and provide the completion status (#597). * Change the internal Configurable API SerializeOptions to return UserProperties (instead of the final string representation). Added ToString methods to the ConfigurableOptions class to complete the serialization of Options properties. @@ -15,6 +15,8 @@ * LOG Reporting: add reporting capabilities to the WriteController and the WriteBufferManager by saving the Loggers of the dbs which are using them internally and issuing WARN msgs to these Loggers whenever the state of the WC and WBM changes in regards to delaying (#556). * Enable speedb features: Use Scoped Pinning Policy in Enable speedb feature (#459). * sst_dump: display metaindex_handle and the index_handle's offset and size in footer information (#404). +* Static Pinning: Set the default for mid-percent capacity threshold in scoped pinning policy to 70 (#689). +* db_bench: Add support for individual scoped pinning policy parameters (#687). ### Bug Fixes * db_bench: Fix SeekRandomWriteRandom valid check. Use key and value only after checking iterator is valid. diff --git a/db_stress_tool/db_stress_gflags.cc b/db_stress_tool/db_stress_gflags.cc index 2e49ab86bf..f876e39b08 100644 --- a/db_stress_tool/db_stress_gflags.cc +++ b/db_stress_tool/db_stress_gflags.cc @@ -23,6 +23,7 @@ #ifdef GFLAGS #include "db_stress_tool/db_stress_common.h" +#include "table/block_based/default_pinning_policy.h" static bool ValidateUint32Range(const char* flagname, uint64_t value) { if (value > std::numeric_limits::max()) { @@ -890,7 +891,12 @@ DEFINE_string(fs_uri, "", " with --env_uri." " Creates a default environment with the specified filesystem."); -DEFINE_string(pinning_policy, "", "URI for registry TablePinningPolicy"); +DEFINE_string(pinning_policy, + ROCKSDB_NAMESPACE::DefaultPinningPolicy::kNickName(), + "The pinning policy to use. " + "The options are: " + "'DefaultPinning': Default RocksDB's pinning polcy. " + "'ScopedPinning': Speedb's Scoped pinning policy."); DEFINE_uint64(ops_per_thread, 1200000, "Number of operations per thread."); static const bool FLAGS_ops_per_thread_dummy __attribute__((__unused__)) = diff --git a/db_stress_tool/db_stress_test_base.cc b/db_stress_tool/db_stress_test_base.cc index c9953f9fc7..f2533b6c62 100644 --- a/db_stress_tool/db_stress_test_base.cc +++ b/db_stress_tool/db_stress_test_base.cc @@ -33,6 +33,7 @@ #include "db_stress_tool/db_stress_compaction_filter.h" #include "db_stress_tool/db_stress_driver.h" #include "db_stress_tool/db_stress_table_properties_collector.h" +#include "plugin/speedb/pinning_policy/scoped_pinning_policy.h" #include "rocksdb/convenience.h" #include "rocksdb/filter_policy.h" #include "rocksdb/options.h" @@ -43,6 +44,7 @@ #include "rocksdb/utilities/object_registry.h" #include "rocksdb/utilities/write_batch_with_index.h" #include "speedb/version.h" +#include "table/block_based/default_pinning_policy.h" #include "test_util/testutil.h" #include "util/cast_util.h" #include "utilities/backup/backup_engine_impl.h" @@ -3166,19 +3168,13 @@ void InitializeOptionsFromFlags( block_based_options.max_auto_readahead_size = FLAGS_max_auto_readahead_size; block_based_options.num_file_reads_for_auto_readahead = FLAGS_num_file_reads_for_auto_readahead; - if (!FLAGS_pinning_policy.empty()) { - ConfigOptions config_options; - config_options.ignore_unknown_options = false; - config_options.ignore_unsupported_options = false; - Status s = TablePinningPolicy::CreateFromString( - config_options, FLAGS_pinning_policy, - &block_based_options.pinning_policy); - if (!s.ok()) { - fprintf(stderr, "Failed to create PinningPolicy: %s\n", - s.ToString().c_str()); - exit(1); - } + + if (FLAGS_pinning_policy == + ROCKSDB_NAMESPACE::ScopedPinningPolicy::kNickName()) { + block_based_options.pinning_policy = + std::make_shared(ScopedPinningOptions()); } + options.table_factory.reset(NewBlockBasedTableFactory(block_based_options)); // Write-Buffer-Manager diff --git a/env/file_system.cc b/env/file_system.cc index 630fa2d221..a64cd68c27 100644 --- a/env/file_system.cc +++ b/env/file_system.cc @@ -1,3 +1,17 @@ +// Copyright (C) 2022 Speedb Ltd. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// // Copyright (c) 2019-present, Facebook, Inc. All rights reserved. // This source code is licensed under both the GPLv2 (found in the // COPYING file in the root directory) and Apache 2.0 License diff --git a/monitoring/statistics.cc b/monitoring/statistics.cc index 2245d511e6..2bf40ca2ba 100644 --- a/monitoring/statistics.cc +++ b/monitoring/statistics.cc @@ -340,6 +340,8 @@ static std::unordered_map stats_type_info = { StatisticsImpl::StatisticsImpl(std::shared_ptr stats) : stats_(std::move(stats)) { RegisterOptions("StatisticsOptions", &stats_, &stats_type_info); + printf("StatisticsData.size=%d\n", (int)sizeof(StatisticsData)); + printf("per_core_stats_.size=%d\n", (int)sizeof(per_core_stats_)); } StatisticsImpl::~StatisticsImpl() {} diff --git a/plugin/speedb/pinning_policy/scoped_pinning_policy.h b/plugin/speedb/pinning_policy/scoped_pinning_policy.h index 431aebc763..1aa636cc77 100644 --- a/plugin/speedb/pinning_policy/scoped_pinning_policy.h +++ b/plugin/speedb/pinning_policy/scoped_pinning_policy.h @@ -22,16 +22,20 @@ namespace ROCKSDB_NAMESPACE { struct TablePinningOptions; struct ScopedPinningOptions { static const char* kName() { return "ScopedPinningOptions"; } + + static constexpr uint32_t kDefaultLastLevelWithDataPercent = 10; + static constexpr uint32_t kDefaultMidPercent = 70; + // Limit to how much data should be pinned size_t capacity = 1024 * 1024 * 1024; // 1GB // Percent of capacity at which not to pin last-leve-with-data data - uint32_t last_level_with_data_percent = 10; + uint32_t last_level_with_data_percent = kDefaultLastLevelWithDataPercent; + // Percent of capacity at which not to pin non-L0 data - uint32_t mid_percent = 80; + uint32_t mid_percent = kDefaultMidPercent; }; -// A table policy that limits the size of the data to be pinned // class ScopedPinningPolicy : public RecordingPinningPolicy { public: @@ -39,7 +43,7 @@ class ScopedPinningPolicy : public RecordingPinningPolicy { ScopedPinningPolicy(const ScopedPinningOptions& options); static const char* kClassName() { return "speedb_scoped_pinning_policy"; } - static const char* kNickName() { return "speedb.ScopedPinningPolicy"; } + static const char* kNickName() { return "scoped"; } const char* Name() const override { return kClassName(); } const char* NickName() const override { return kNickName(); } std::string GetId() const override; diff --git a/table/block_based/default_pinning_policy.h b/table/block_based/default_pinning_policy.h index 23e5f2c96b..292b39b809 100644 --- a/table/block_based/default_pinning_policy.h +++ b/table/block_based/default_pinning_policy.h @@ -37,7 +37,9 @@ class DefaultPinningPolicy : public RecordingPinningPolicy { bool pin_l0); static const char* kClassName() { return "DefaultPinningPolicy"; } + static const char* kNickName() { return "default"; } const char* Name() const override { return kClassName(); } + const char* NickName() const override { return kNickName(); } protected: bool CheckPin(const TablePinningOptions& tpo, uint8_t type, size_t /*size*/, diff --git a/table/block_based/table_pinning_policy.cc b/table/block_based/table_pinning_policy.cc index f2f028e5ff..7155d44336 100644 --- a/table/block_based/table_pinning_policy.cc +++ b/table/block_based/table_pinning_policy.cc @@ -51,7 +51,9 @@ class DefaultPinningPolicy : public RecordingPinningPolicy { //**TODO: Register options? } static const char* kClassName() { return "DefaultPinningPolicy"; } + static const char* kNickName() { return "DefaultPinning"; } const char* Name() const override { return kClassName(); } + const char* NickName() const override { return kNickName(); } protected: bool CheckPin(const TablePinningOptions& tpo, uint8_t type, size_t /*size*/, diff --git a/tools/db_bench_tool.cc b/tools/db_bench_tool.cc index 27860bdded..8ad81a1a38 100644 --- a/tools/db_bench_tool.cc +++ b/tools/db_bench_tool.cc @@ -11,7 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. - +// // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. // This source code is licensed under both the GPLv2 (found in the // COPYING file in the root directory) and Apache 2.0 License @@ -61,6 +61,7 @@ #include "monitoring/histogram.h" #include "monitoring/statistics.h" #include "options/cf_options.h" +#include "plugin/speedb/pinning_policy/scoped_pinning_policy.h" #include "port/port.h" #include "port/stack_trace.h" #include "rocksdb/cache.h" @@ -92,6 +93,7 @@ #include "rocksdb/write_batch.h" #include "rocksdb/write_buffer_manager.h" #include "speedb/version.h" +#include "table/block_based/default_pinning_policy.h" #include "test_util/testutil.h" #include "test_util/transaction_test_util.h" #include "tools/simulated_hybrid_file_system.h" @@ -818,7 +820,32 @@ DEFINE_bool( " Note `cache_index_and_filter_blocks` must be true for this option to have" " any effect."); -DEFINE_string(pinning_policy, "", "URI for registry TablePinningPolicy"); +DEFINE_string(pinning_policy, + ROCKSDB_NAMESPACE::DefaultPinningPolicy::kNickName(), + "The pinning policy to use. " + "The options are: " + "'default': Default RocksDB's pinning polcy. " + "'scoped': Speedb's Scoped pinning policy."); + +DEFINE_int32(scoped_pinning_capacity, -1, + "Pinning policy capacity. The default (-1) results in the " + "capacity being calculated " + "automatically. If the capacity is >= 0, the specified value will " + "be the capacity. Applicable only when pinning_policy=='Scoped'."); + +DEFINE_int32( + scoped_pinning_last_level_with_data_percent, + ROCKSDB_NAMESPACE::ScopedPinningOptions::kDefaultLastLevelWithDataPercent, + "Max percent of the pinning capacity to pin entites that are at " + "the bottom-most possible level." + "Applicable only when pinning_policy=='Scoped'."); + +DEFINE_int32(scoped_pinning_mid_percent, + ROCKSDB_NAMESPACE::ScopedPinningOptions::kDefaultMidPercent, + "Max percent of the pinning capacity to pin entites that are " + "above the bottom-most level,but at a >0 level. " + "Must be >= scoped_pinning_last_level_with_data_percent. " + "Applicable only when pinning_policy=='Scoped'."); DEFINE_int32(block_size, static_cast( @@ -4817,14 +4844,28 @@ class Benchmark { } else { fprintf(stdout, "Integrated BlobDB: blob cache disabled\n"); } - if (!FLAGS_pinning_policy.empty()) { - s = TablePinningPolicy::CreateFromString( - config_options, FLAGS_pinning_policy, - &block_based_options.pinning_policy); - if (!s.ok()) { - ErrorExit("Could not create pinning policy: %s", - s.ToString().c_str()); + + if (FLAGS_pinning_policy == + ROCKSDB_NAMESPACE::ScopedPinningPolicy::kNickName()) { + ScopedPinningOptions pinning_options; + + size_t pinning_capacity = 0U; + if (FLAGS_scoped_pinning_capacity >= 0) { + pinning_capacity = FLAGS_scoped_pinning_capacity; + } else { + auto cache_capacity = FLAGS_cache_size; + if (FLAGS_cost_write_buffer_to_cache) { + assert(cache_capacity >= FLAGS_db_write_buffer_size); + cache_capacity -= FLAGS_db_write_buffer_size; + } + pinning_capacity = (80 * cache_capacity) / 100; } + pinning_options.capacity = pinning_capacity; + pinning_options.last_level_with_data_percent = + FLAGS_scoped_pinning_last_level_with_data_percent; + pinning_options.mid_percent = FLAGS_scoped_pinning_mid_percent; + block_based_options.pinning_policy = + std::make_shared(pinning_options); } options.table_factory.reset( @@ -9279,6 +9320,55 @@ void ValidateMetadataCacheOptions() { } } +void ValidatePinningRelatedOptions() { + if (FLAGS_pinning_policy == + ROCKSDB_NAMESPACE::DefaultPinningPolicy::kNickName()) { + return; + } else if (FLAGS_pinning_policy == + ROCKSDB_NAMESPACE::ScopedPinningPolicy::kNickName()) { + if (FLAGS_cache_index_and_filter_blocks == false) { + ErrorExit( + "--cache_index_and_filter_blocks must be set when " + "--pinning_policy=='%s' to have any affect.", + ROCKSDB_NAMESPACE::ScopedPinningPolicy::kNickName()); + } + + if (FLAGS_scoped_pinning_capacity < -1) { + ErrorExit( + "--scoped_pinning_capacity must be either -1 (auto-calc) or >= 0"); + } + + if ((FLAGS_scoped_pinning_last_level_with_data_percent < 0) || + (FLAGS_scoped_pinning_last_level_with_data_percent > 100)) { + ErrorExit( + "--scoped_pinning_last_level_with_data_percent must be between 0 and " + "100"); + } + + if ((FLAGS_scoped_pinning_mid_percent < 0) || + (FLAGS_scoped_pinning_mid_percent > 100)) { + ErrorExit("--scoped_pinning_mid_percent must be between 0 and 100"); + } + + if (FLAGS_scoped_pinning_last_level_with_data_percent >= + FLAGS_scoped_pinning_mid_percent) { + ErrorExit( + "--scoped_pinning_last_level_with_data_percent must be <= " + "--scoped_pinning_mid_percent must be between 0 and 100"); + } + + if (FLAGS_cost_write_buffer_to_cache) { + if (FLAGS_db_write_buffer_size > FLAGS_cache_size) { + ErrorExit("--cache_size must be >= --db_write_buffer_size"); + } + } + } else { + ErrorExit("--pinning_policy must be either %s or %s", + ROCKSDB_NAMESPACE::DefaultPinningPolicy::kNickName(), + ROCKSDB_NAMESPACE::ScopedPinningPolicy::kNickName()); + } +} + namespace { // Records the values of applicable flags during the invocation of the first // group The user may not modify any of these in subsequent groups @@ -9460,12 +9550,6 @@ void ValidateMetadataCacheOptions() { } void ValidatePinningPolicyRelatedFlags() { - if (!FLAGS_pinning_policy.empty() && FLAGS_enable_speedb_features) { - ErrorExit( - "--pinning_policy should not be set when --unpartitioned_pinning is " - "set."); - } - if (FLAGS_enable_speedb_features) { if (gflags::GetCommandLineFlagInfoOrDie("max_background_jobs").is_default || gflags::GetCommandLineFlagInfoOrDie("total_ram_size").is_default) { @@ -9605,6 +9689,7 @@ int db_bench_tool_run_group(int group_num, int num_groups, int argc, } ValidateMetadataCacheOptions(); + ValidatePinningRelatedOptions(); ParseSanitizeAndValidateMultipleDBsFlags(first_group); if (first_group) { @@ -9686,6 +9771,8 @@ int db_bench_tool_run_group(int group_num, int num_groups, int argc, // runner of the failed group (subsequent groups will NOT be run). // int db_bench_tool(int argc, char** argv) { + printf("StatisticsImpl.size=%d\n", (int)sizeof(StatisticsImpl)); + ROCKSDB_NAMESPACE::port::InstallStackTraceHandler(); static bool initialized = false; if (!initialized) { diff --git a/tools/db_crashtest.py b/tools/db_crashtest.py index 7bb4b34a50..e72dcc566e 100644 --- a/tools/db_crashtest.py +++ b/tools/db_crashtest.py @@ -1,4 +1,17 @@ #!/usr/bin/env python3 +# Copyright (C) 2023 Speedb Ltd. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. from __future__ import absolute_import, division, print_function, unicode_literals @@ -223,7 +236,7 @@ "customopspercent": 0, # "filter_uri": lambda: random.choice(["speedb.PairedBloomFilter", ""]), "memtablerep": lambda: random.choice(["skip_list", "hash_spdb"]), - "pinning_policy": lambda: random.choice(["", "speedb_scoped_pinning_policy"]), + "pinning_policy": lambda: random.choice(["default", "scoped"]), "use_dynamic_delay": lambda: random.choice([0, 1, 1, 1]), "allow_wbm_stalls": lambda: random.randint(0, 1), "start_delay_percent": lambda: random.randint(0, 99), @@ -767,6 +780,10 @@ def finalize_and_sanitize(src_params, counter): dest_params["bloom_bits"] = random.choice([random.randint(1,19), random.lognormvariate(2.3, 1.3)]) + # db_bench will abort if using ScopedPinningPolicy and not setting cache_index_and_filter_blocks + if dest_params.get("pinning_policy") == "ScopedPinning": + dest_params["cache_index_and_filter_blocks"] + return dest_params