| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498 |
- // 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).
- #include "util/ribbon_config.h"
- namespace ROCKSDB_NAMESPACE::ribbon::detail {
- // Each instantiation of this struct is sufficiently unique for configuration
- // purposes, and is only instantiated for settings where we support the
- // configuration API. An application might only reference one instantiation,
- // meaning the rest could be pruned at link time.
- template <ConstructionFailureChance kCfc, uint64_t kCoeffBits, bool kUseSmash>
- struct BandingConfigHelperData {
- static constexpr size_t kKnownSize = 18U;
- // Because of complexity in the data, for smaller numbers of slots
- // (powers of two up to 2^17), we record known numbers that can be added
- // with kCfc chance of construction failure and settings in template
- // parameters. Zero means "unsupported (too small) number of slots".
- // (GetNumToAdd below will use interpolation for numbers of slots
- // between powers of two; double rather than integer values here make
- // that more accurate.)
- static const std::array<double, kKnownSize> kKnownToAddByPow2;
- // For sufficiently large number of slots, doubling the number of
- // slots will increase the expected overhead (slots over number added)
- // by approximately this constant.
- // (This is roughly constant regardless of ConstructionFailureChance and
- // smash setting.)
- // (Would be a constant if we had partial template specialization for
- // static const members.)
- static inline double GetFactorPerPow2() {
- if (kCoeffBits == 128U) {
- return 0.0038;
- } else {
- assert(kCoeffBits == 64U);
- return 0.0083;
- }
- }
- // Overhead factor for 2^(kKnownSize-1) slots
- // (Would be a constant if we had partial template specialization for
- // static const members.)
- static inline double GetFinalKnownFactor() {
- return 1.0 * (uint32_t{1} << (kKnownSize - 1)) /
- kKnownToAddByPow2[kKnownSize - 1];
- }
- // GetFinalKnownFactor() - (kKnownSize-1) * GetFactorPerPow2()
- // (Would be a constant if we had partial template specialization for
- // static const members.)
- static inline double GetBaseFactor() {
- return GetFinalKnownFactor() - (kKnownSize - 1) * GetFactorPerPow2();
- }
- // Get overhead factor (slots over number to add) for sufficiently large
- // number of slots (by log base 2)
- static inline double GetFactorForLarge(double log2_num_slots) {
- return GetBaseFactor() + log2_num_slots * GetFactorPerPow2();
- }
- // For a given power of two number of slots (specified by whole number
- // log base 2), implements GetNumToAdd for such limited case, returning
- // double for better interpolation in GetNumToAdd and GetNumSlots.
- static inline double GetNumToAddForPow2(uint32_t log2_num_slots) {
- assert(log2_num_slots <= 32); // help clang-analyze
- if (log2_num_slots < kKnownSize) {
- return kKnownToAddByPow2[log2_num_slots];
- } else {
- return 1.0 * (uint64_t{1} << log2_num_slots) /
- GetFactorForLarge(1.0 * log2_num_slots);
- }
- }
- };
- // Based on data from FindOccupancy in ribbon_test
- template <>
- const std::array<double, 18>
- BandingConfigHelperData<kOneIn2, 128U, false>::kKnownToAddByPow2{{
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0, // unsupported
- 252.984,
- 506.109,
- 1013.71,
- 2029.47,
- 4060.43,
- 8115.63,
- 16202.2,
- 32305.1,
- 64383.5,
- 128274,
- }};
- template <>
- const std::array<double, 18>
- BandingConfigHelperData<kOneIn2, 128U, /*smash*/ true>::kKnownToAddByPow2{{
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0, // unsupported
- 126.274,
- 254.279,
- 510.27,
- 1022.24,
- 2046.02,
- 4091.99,
- 8154.98,
- 16244.3,
- 32349.7,
- 64426.6,
- 128307,
- }};
- template <>
- const std::array<double, 18>
- BandingConfigHelperData<kOneIn2, 64U, false>::kKnownToAddByPow2{{
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0, // unsupported
- 124.94,
- 249.968,
- 501.234,
- 1004.06,
- 2006.15,
- 3997.89,
- 7946.99,
- 15778.4,
- 31306.9,
- 62115.3,
- 123284,
- }};
- template <>
- const std::array<double, 18>
- BandingConfigHelperData<kOneIn2, 64U, /*smash*/ true>::kKnownToAddByPow2{{
- 0,
- 0,
- 0,
- 0,
- 0,
- 0, // unsupported
- 62.2683,
- 126.259,
- 254.268,
- 509.975,
- 1019.98,
- 2026.16,
- 4019.75,
- 7969.8,
- 15798.2,
- 31330.3,
- 62134.2,
- 123255,
- }};
- template <>
- const std::array<double, 18>
- BandingConfigHelperData<kOneIn20, 128U, false>::kKnownToAddByPow2{{
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0, // unsupported
- 248.851,
- 499.532,
- 1001.26,
- 2003.97,
- 4005.59,
- 8000.39,
- 15966.6,
- 31828.1,
- 63447.3,
- 126506,
- }};
- template <>
- const std::array<double, 18>
- BandingConfigHelperData<kOneIn20, 128U, /*smash*/ true>::kKnownToAddByPow2{{
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0, // unsupported
- 122.637,
- 250.651,
- 506.625,
- 1018.54,
- 2036.43,
- 4041.6,
- 8039.25,
- 16005,
- 31869.6,
- 63492.8,
- 126537,
- }};
- template <>
- const std::array<double, 18>
- BandingConfigHelperData<kOneIn20, 64U, false>::kKnownToAddByPow2{{
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0, // unsupported
- 120.659,
- 243.346,
- 488.168,
- 976.373,
- 1948.86,
- 3875.85,
- 7704.97,
- 15312.4,
- 30395.1,
- 60321.8,
- 119813,
- }};
- template <>
- const std::array<double, 18>
- BandingConfigHelperData<kOneIn20, 64U, /*smash*/ true>::kKnownToAddByPow2{{
- 0,
- 0,
- 0,
- 0,
- 0,
- 0, // unsupported
- 58.6016,
- 122.619,
- 250.641,
- 503.595,
- 994.165,
- 1967.36,
- 3898.17,
- 7727.21,
- 15331.5,
- 30405.8,
- 60376.2,
- 119836,
- }};
- template <>
- const std::array<double, 18>
- BandingConfigHelperData<kOneIn1000, 128U, false>::kKnownToAddByPow2{{
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0, // unsupported
- 242.61,
- 491.887,
- 983.603,
- 1968.21,
- 3926.98,
- 7833.99,
- 15629,
- 31199.9,
- 62307.8,
- 123870,
- }};
- template <>
- const std::array<double, 18> BandingConfigHelperData<
- kOneIn1000, 128U, /*smash*/ true>::kKnownToAddByPow2{{
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0, // unsupported
- 117.19,
- 245.105,
- 500.748,
- 1010.67,
- 1993.4,
- 3950.01,
- 7863.31,
- 15652,
- 31262.1,
- 62462.8,
- 124095,
- }};
- template <>
- const std::array<double, 18>
- BandingConfigHelperData<kOneIn1000, 64U, false>::kKnownToAddByPow2{{
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0, // unsupported
- 114,
- 234.8,
- 471.498,
- 940.165,
- 1874,
- 3721.5,
- 7387.5,
- 14592,
- 29160,
- 57745,
- 115082,
- }};
- template <>
- const std::array<double, 18>
- BandingConfigHelperData<kOneIn1000, 64U, /*smash*/ true>::kKnownToAddByPow2{
- {
- 0,
- 0,
- 0,
- 0,
- 0,
- 0, // unsupported
- 53.0434,
- 117,
- 245.312,
- 483.571,
- 950.251,
- 1878,
- 3736.34,
- 7387.97,
- 14618,
- 29142.9,
- 57838.8,
- 114932,
- }};
- // We hide these implementation details from the .h file with explicit
- // instantiations below these partial specializations.
- template <ConstructionFailureChance kCfc, uint64_t kCoeffBits, bool kUseSmash,
- bool kHomogeneous>
- uint32_t BandingConfigHelper1MaybeSupported<
- kCfc, kCoeffBits, kUseSmash, kHomogeneous,
- true /* kIsSupported */>::GetNumToAdd(uint32_t num_slots) {
- using Data = detail::BandingConfigHelperData<kCfc, kCoeffBits, kUseSmash>;
- if (num_slots == 0) {
- return 0;
- }
- uint32_t num_to_add;
- double log2_num_slots = std::log(num_slots) * 1.4426950409;
- uint32_t floor_log2 = static_cast<uint32_t>(log2_num_slots);
- if (floor_log2 + 1 < Data::kKnownSize) {
- double ceil_portion = 1.0 * num_slots / (uint32_t{1} << floor_log2) - 1.0;
- // Must be a supported number of slots
- assert(Data::kKnownToAddByPow2[floor_log2] > 0.0);
- // Weighted average of two nearest known data points
- num_to_add = static_cast<uint32_t>(
- ceil_portion * Data::kKnownToAddByPow2[floor_log2 + 1] +
- (1.0 - ceil_portion) * Data::kKnownToAddByPow2[floor_log2]);
- } else {
- // Use formula for large values
- double factor = Data::GetFactorForLarge(log2_num_slots);
- assert(factor >= 1.0);
- num_to_add = static_cast<uint32_t>(num_slots / factor);
- }
- if (kHomogeneous) {
- // Even when standard filter construction would succeed, we might
- // have loaded things up too much for Homogeneous filter. (Complete
- // explanation not known but observed empirically.) This seems to
- // correct for that, mostly affecting small filter configurations.
- if (num_to_add >= 8) {
- num_to_add -= 8;
- } else {
- assert(false);
- }
- }
- return num_to_add;
- }
- template <ConstructionFailureChance kCfc, uint64_t kCoeffBits, bool kUseSmash,
- bool kHomogeneous>
- uint32_t BandingConfigHelper1MaybeSupported<
- kCfc, kCoeffBits, kUseSmash, kHomogeneous,
- true /* kIsSupported */>::GetNumSlots(uint32_t num_to_add) {
- using Data = detail::BandingConfigHelperData<kCfc, kCoeffBits, kUseSmash>;
- if (num_to_add == 0) {
- return 0;
- }
- if (kHomogeneous) {
- // Reverse of above in GetNumToAdd
- num_to_add += 8;
- }
- double log2_num_to_add = std::log(num_to_add) * 1.4426950409;
- uint32_t approx_log2_slots = static_cast<uint32_t>(log2_num_to_add + 0.5);
- assert(approx_log2_slots <= 32); // help clang-analyze
- double lower_num_to_add = Data::GetNumToAddForPow2(approx_log2_slots);
- double upper_num_to_add;
- if (approx_log2_slots == 0 || lower_num_to_add == /* unsupported */ 0) {
- // Return minimum non-zero slots in standard implementation
- return kUseSmash ? kCoeffBits : 2 * kCoeffBits;
- } else if (num_to_add < lower_num_to_add) {
- upper_num_to_add = lower_num_to_add;
- --approx_log2_slots;
- lower_num_to_add = Data::GetNumToAddForPow2(approx_log2_slots);
- } else {
- upper_num_to_add = Data::GetNumToAddForPow2(approx_log2_slots + 1);
- }
- assert(num_to_add >= lower_num_to_add);
- assert(num_to_add < upper_num_to_add);
- double upper_portion =
- (num_to_add - lower_num_to_add) / (upper_num_to_add - lower_num_to_add);
- double lower_num_slots = 1.0 * (uint64_t{1} << approx_log2_slots);
- // Interpolation, round up
- return static_cast<uint32_t>(upper_portion * lower_num_slots +
- lower_num_slots + 0.999999999);
- }
- // These explicit instantiations enable us to hide most of the
- // implementation details from the .h file. (The .h file currently
- // needs to determine whether settings are "supported" or not.)
- template struct BandingConfigHelper1MaybeSupported<kOneIn2, 128U, /*sm*/ false,
- /*hm*/ false, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<kOneIn2, 128U, /*sm*/ true,
- /*hm*/ false, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<kOneIn2, 128U, /*sm*/ false,
- /*hm*/ true, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<kOneIn2, 128U, /*sm*/ true,
- /*hm*/ true, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<kOneIn2, 64U, /*sm*/ false,
- /*hm*/ false, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<kOneIn2, 64U, /*sm*/ true,
- /*hm*/ false, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<kOneIn2, 64U, /*sm*/ false,
- /*hm*/ true, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<kOneIn2, 64U, /*sm*/ true,
- /*hm*/ true, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<kOneIn20, 128U, /*sm*/ false,
- /*hm*/ false, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<kOneIn20, 128U, /*sm*/ true,
- /*hm*/ false, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<kOneIn20, 128U, /*sm*/ false,
- /*hm*/ true, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<kOneIn20, 128U, /*sm*/ true,
- /*hm*/ true, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<kOneIn20, 64U, /*sm*/ false,
- /*hm*/ false, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<kOneIn20, 64U, /*sm*/ true,
- /*hm*/ false, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<kOneIn20, 64U, /*sm*/ false,
- /*hm*/ true, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<kOneIn20, 64U, /*sm*/ true,
- /*hm*/ true, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<
- kOneIn1000, 128U, /*sm*/ false, /*hm*/ false, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<
- kOneIn1000, 128U, /*sm*/ true, /*hm*/ false, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<
- kOneIn1000, 128U, /*sm*/ false, /*hm*/ true, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<
- kOneIn1000, 128U, /*sm*/ true, /*hm*/ true, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<
- kOneIn1000, 64U, /*sm*/ false, /*hm*/ false, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<kOneIn1000, 64U, /*sm*/ true,
- /*hm*/ false, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<
- kOneIn1000, 64U, /*sm*/ false, /*hm*/ true, /*sup*/ true>;
- template struct BandingConfigHelper1MaybeSupported<kOneIn1000, 64U, /*sm*/ true,
- /*hm*/ true, /*sup*/ true>;
- } // namespace ROCKSDB_NAMESPACE::ribbon::detail
|