// Copyright (c) Facebook, Inc. and its affiliates. 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 // (found in the LICENSE.Apache file in the root directory). #pragma once #include #include #include #include #include "port/lang.h" // for FALLTHROUGH_INTENDED #include "rocksdb/rocksdb_namespace.h" namespace ROCKSDB_NAMESPACE { namespace ribbon { // RIBBON PHSF & RIBBON Filter (Rapid Incremental Boolean Banding ON-the-fly) // // ribbon_config.h: APIs for relating numbers of slots with numbers of // additions for tolerable construction failure probabilities. This is // separate from ribbon_impl.h because it might not be needed for // some applications. // // This API assumes uint32_t for number of slots, as a single Ribbon // linear system should not normally overflow that without big penalties. // // Template parameter kCoeffBits uses uint64_t for convenience in case it // comes from size_t. // // Most of the complexity here is trying to optimize speed and // compiled code size, using templates to minimize table look-ups and // the compiled size of all linked look-up tables. Look-up tables are // required because we don't have good formulas, and the data comes // from running FindOccupancy in ribbon_test. // Represents a chosen chance of successful Ribbon construction for a single // seed. Allowing higher chance of failed construction can reduce space // overhead but takes extra time in construction. enum ConstructionFailureChance { kOneIn2, kOneIn20, // When using kHomogeneous==true, construction failure chance should // not generally exceed target FP rate, so it unlikely useful to // allow a higher "failure" chance. In some cases, even more overhead // is appropriate. (TODO) kOneIn1000, }; namespace detail { // It is useful to compile ribbon_test linking to BandingConfigHelper with // settings for which we do not have configuration data, as long as we don't // run the code. This template hack supports that. template struct BandingConfigHelper1MaybeSupported { public: static uint32_t GetNumToAdd(uint32_t num_slots) { // Unsupported assert(num_slots == 0); (void)num_slots; return 0; } static uint32_t GetNumSlots(uint32_t num_to_add) { // Unsupported assert(num_to_add == 0); (void)num_to_add; return 0; } }; // Base class for BandingConfigHelper1 and helper for BandingConfigHelper // with core implementations built on above data template struct BandingConfigHelper1MaybeSupported< kCfc, kCoeffBits, kUseSmash, kHomogeneous, true /* kIsSupported */> { public: // See BandingConfigHelper1. Implementation in ribbon_config.cc static uint32_t GetNumToAdd(uint32_t num_slots); // See BandingConfigHelper1. Implementation in ribbon_config.cc static uint32_t GetNumSlots(uint32_t num_to_add); }; } // namespace detail template struct BandingConfigHelper1 : public detail::BandingConfigHelper1MaybeSupported< kCfc, kCoeffBits, kUseSmash, kHomogeneous, /* kIsSupported */ kCoeffBits == 64 || kCoeffBits == 128> { public: // Returns a number of entries that can be added to a given number of // slots, with roughly kCfc chance of construction failure per seed, // or better. Does NOT do rounding for InterleavedSoln; call // RoundUpNumSlots for that. // // inherited: // static uint32_t GetNumToAdd(uint32_t num_slots); // Returns a number of slots for a given number of entries to add // that should have roughly kCfc chance of construction failure per // seed, or better. Does NOT do rounding for InterleavedSoln; call // RoundUpNumSlots for that. // // num_to_add should not exceed roughly 2/3rds of the maximum value // of the uint32_t type to avoid overflow. // // inherited: // static uint32_t GetNumSlots(uint32_t num_to_add); }; // Configured using TypesAndSettings as in ribbon_impl.h template struct BandingConfigHelper1TS : public BandingConfigHelper1< kCfc, /* kCoeffBits */ sizeof(typename TypesAndSettings::CoeffRow) * 8U, TypesAndSettings::kUseSmash, TypesAndSettings::kHomogeneous> {}; // Like BandingConfigHelper1TS except failure chance can be a runtime rather // than compile time value. template struct BandingConfigHelper { public: static constexpr ConstructionFailureChance kDefaultFailureChance = TypesAndSettings::kHomogeneous ? kOneIn1000 : kOneIn20; static uint32_t GetNumToAdd( uint32_t num_slots, ConstructionFailureChance max_failure = kDefaultFailureChance) { switch (max_failure) { default: assert(false); FALLTHROUGH_INTENDED; case kOneIn20: { using H1 = BandingConfigHelper1TS; return H1::GetNumToAdd(num_slots); } case kOneIn2: { using H1 = BandingConfigHelper1TS; return H1::GetNumToAdd(num_slots); } case kOneIn1000: { using H1 = BandingConfigHelper1TS; return H1::GetNumToAdd(num_slots); } } } static uint32_t GetNumSlots( uint32_t num_to_add, ConstructionFailureChance max_failure = kDefaultFailureChance) { switch (max_failure) { default: assert(false); FALLTHROUGH_INTENDED; case kOneIn20: { using H1 = BandingConfigHelper1TS; return H1::GetNumSlots(num_to_add); } case kOneIn2: { using H1 = BandingConfigHelper1TS; return H1::GetNumSlots(num_to_add); } case kOneIn1000: { using H1 = BandingConfigHelper1TS; return H1::GetNumSlots(num_to_add); } } } }; } // namespace ribbon } // namespace ROCKSDB_NAMESPACE