From: Igor Fedotov Date: Thu, 7 Mar 2024 17:42:18 +0000 (+0300) Subject: os/bluestore: refactor allocator's ExtentCollectionTraits X-Git-Tag: v19.2.3~223^2~1 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=bc2e61af66789fee5abb9eff02deaaf1f8f6655c;p=ceph.git os/bluestore: refactor allocator's ExtentCollectionTraits Signed-off-by: Igor Fedotov --- diff --git a/src/os/bluestore/Allocator.cc b/src/os/bluestore/Allocator.cc index 90e3224c56ac7..f6a3654ab3c0d 100644 --- a/src/os/bluestore/Allocator.cc +++ b/src/os/bluestore/Allocator.cc @@ -284,7 +284,7 @@ void Allocator::FreeStateHistogram::record_extent(uint64_t alloc_unit, uint64_t off, uint64_t len) { - size_t idx = myTraits._get_p2_size_bucket(len); + size_t idx = myTraits._get_bucket(len); ceph_assert(idx < buckets.size()); ++buckets[idx].total; @@ -293,7 +293,7 @@ void Allocator::FreeStateHistogram::record_extent(uint64_t alloc_unit, auto delta = p2roundup(off, alloc_unit) - off; if (len >= delta + alloc_unit) { len -= delta; - idx = myTraits._get_p2_size_bucket(len); + idx = myTraits._get_bucket(len); ceph_assert(idx < buckets.size()); ++buckets[idx].aligned; buckets[idx].alloc_units += len / alloc_unit; @@ -307,7 +307,7 @@ void Allocator::FreeStateHistogram::foreach( { size_t i = 0; for (const auto& b : buckets) { - cb(myTraits._get_p2_size_bucket_max(i), + cb(myTraits._get_bucket_max(i), b.total, b.aligned, b.alloc_units); ++i; } diff --git a/src/os/bluestore/Allocator.h b/src/os/bluestore/Allocator.h index 089b699b0762c..e276307765060 100644 --- a/src/os/bluestore/Allocator.h +++ b/src/os/bluestore/Allocator.h @@ -24,20 +24,24 @@ typedef release_set_t::value_type release_set_entry_t; class Allocator { protected: - struct ExtentCollectionTraits { + /** + * This is a base set of traits for logical placing entries + * into limited collection of buckets depending on their sizes. + * Descandants should implement get_bucket(len) method to obtain + * bucket index using entry length. + */ + struct LenPartitionedSetTraits { size_t num_buckets; - size_t base_bits; // min extent size - size_t base = 1ull << base_bits; - size_t factor; // single bucket size range to be - // determined as [len, len * factor * 2) - // for log2(len) indexing and - // [len, len + factor * base) - // for linear indexing. + size_t base_bits; // bits in min entry size + size_t base; // min entry size + size_t factor; // additional factor to be applied + // to entry size when calculating + // target bucket - ExtentCollectionTraits(size_t _num_buckets, - size_t _base_bits = 12, //= 4096 bytes - size_t _factor = 1) : + LenPartitionedSetTraits(size_t _num_buckets, + size_t _base_bits = 12, //= 4096 bytes + size_t _factor = 1) : num_buckets(_num_buckets), base_bits(_base_bits), base(1ull << base_bits), @@ -45,13 +49,63 @@ protected: { ceph_assert(factor); } + }; + + /** + * This extends LenPartitionedSetTraits to implement linear bucket indexing: + * bucket index to be determined as entry's size divided by (base * factor), + * i.e. buckets are: + * [0..base) + * [base, base+base*factor) + * [base+base*factor, base+base*factor*2) + * [base+base*factor*2, base+base*factor*3) + * ... + */ + struct LenPartitionedSetTraitsLinear : public LenPartitionedSetTraits { + using LenPartitionedSetTraits::LenPartitionedSetTraits; + /* + * Determines bucket index for a given extent's length in a bucket set + * with linear (len / base / factor) indexing. + * The first bucket is targeted for lengths < base, + * the last bucket is used for lengths above the maximum + * detemined by bucket count. + */ + inline size_t _get_bucket(uint64_t len) const { + size_t idx = (len / factor) >> base_bits; + idx = idx < num_buckets ? idx : num_buckets - 1; + return idx; + } + /* + * returns upper bound of a specific bucket + */ + inline size_t _get_bucket_max(size_t bucket) const { + return + bucket < num_buckets - 1 ? + base * factor * (1 + bucket) : + std::numeric_limits::max(); + } + }; + /** + * This extends LenPartitionedSetTraits to implement exponential bucket indexing: + * target bucket bounds are determined as + * [0, base] + * (base, base*2^factor] + * (base*2^factor, base*2^(factor*2)] + * (base*2^(factor*2), base*2^(factor*3)] + * ... + * + */ + struct LenPartitionedSetTraitsPow2 : public LenPartitionedSetTraits { /* * Determines bucket index for a given extent's length in a bucket collection * with log2(len) indexing. - * The last bucket index is returned for lengths above the maximum. + * The first bucket is targeted for lengths < base, + * The last bucket index is used for lengths above the maximum + * detemined by bucket count. */ - inline size_t _get_p2_size_bucket(uint64_t len) const { + using LenPartitionedSetTraits::LenPartitionedSetTraits; + inline size_t _get_bucket(uint64_t len) const { size_t idx; const size_t len_p2_max = base << ((factor * (num_buckets - 2))); @@ -69,33 +123,12 @@ protected: /* * returns upper bound of the bucket with log2(len) indexing. */ - inline size_t _get_p2_size_bucket_max(size_t bucket) const { + inline size_t _get_bucket_max(size_t bucket) const { return bucket < num_buckets - 1 ? base << (factor * bucket) : std::numeric_limits::max(); - }; - - /* - * Determines bucket index for a given extent's length in a bucket collection - * with linear (len / min_extent_size) indexing. - * The last bucket index is returned for lengths above the maximum. - */ - inline size_t _get_linear_size_bucket(uint64_t len) const { - size_t idx = (len / factor) >> base_bits; - idx = idx < num_buckets ? idx : num_buckets - 1; - return idx; } - /* - * returns upper bound of the bucket with - * linear(len / min_extent_size) indexing. - */ - inline size_t _get_linear_size_bucket_max(size_t bucket) const { - return - bucket < num_buckets - 1 ? - base * factor * (1 + bucket) : - std::numeric_limits::max(); - }; }; /* @@ -145,7 +178,7 @@ protected: * extents aren't not cached. */ class OpportunisticExtentCache { - const Allocator::ExtentCollectionTraits myTraits; + const LenPartitionedSetTraitsLinear myTraits; enum { BUCKET_COUNT = 16, EXTENTS_PER_BUCKET = 16, // amount of entries per single bucket, @@ -179,7 +212,7 @@ protected: bool ret = false; ceph_assert(p2aligned(offset, myTraits.base)); ceph_assert(p2aligned(len, myTraits.base)); - auto idx = myTraits._get_linear_size_bucket(len); + auto idx = myTraits._get_bucket(len); if (idx < buckets.size()) ret = buckets[idx].try_put(offset); lock.unlock_shared(); @@ -295,7 +328,7 @@ public: // - amount of allocation units in aligned extents // class FreeStateHistogram { - const Allocator::ExtentCollectionTraits myTraits; + const LenPartitionedSetTraitsPow2 myTraits; enum { BASE_BITS = 12, // 4096 bytes FACTOR = 2, diff --git a/src/os/bluestore/Btree2Allocator.cc b/src/os/bluestore/Btree2Allocator.cc index 33ee6348c8e03..9e421b6762eb0 100644 --- a/src/os/bluestore/Btree2Allocator.cc +++ b/src/os/bluestore/Btree2Allocator.cc @@ -197,7 +197,7 @@ int64_t Btree2Allocator::_allocate( continue; } } - size_t bucket0 = myTraits._get_p2_size_bucket(want_now); + size_t bucket0 = myTraits._get_bucket(want_now); int64_t r = __allocate(bucket0, want_now, unit, extents); if (r < 0) { @@ -331,7 +331,7 @@ int64_t Btree2Allocator::__allocate( auto rs_p = _pick_block(0, rs_tree, size); if (rs_p == rs_tree->end()) { - auto bucket_center = myTraits._get_p2_size_bucket(weight_center); + auto bucket_center = myTraits._get_bucket(weight_center); // requested size is to the left of weight center // hence we try to search up toward it first @@ -467,7 +467,7 @@ void Btree2Allocator::_remove_from_tree( uint64_t end) { range_seg_t rs(rt_p->first, rt_p->second); - size_t bucket = myTraits._get_p2_size_bucket(rs.length()); + size_t bucket = myTraits._get_bucket(rs.length()); range_size_tree_t* rs_tree = &range_size_set[bucket]; auto rs_p = rs_tree->find(rs); ceph_assert(rs_p != rs_tree->end()); @@ -571,7 +571,7 @@ bool Btree2Allocator::__try_insert_range( void Btree2Allocator::_range_size_tree_add(const range_seg_t& rs) { auto l = rs.length(); ceph_assert(rs.end > rs.start); - size_t bucket = myTraits._get_p2_size_bucket(l); + size_t bucket = myTraits._get_bucket(l); range_size_set[bucket].insert(rs); num_free += l; @@ -584,7 +584,7 @@ void Btree2Allocator::_range_size_tree_add(const range_seg_t& rs) { } void Btree2Allocator::_range_size_tree_rm(const range_seg_t& rs) { - size_t bucket = myTraits._get_p2_size_bucket(rs.length()); + size_t bucket = myTraits._get_bucket(rs.length()); range_size_tree_t* rs_tree = &range_size_set[bucket]; ceph_assert(rs_tree->size() > 0); auto rs_p = rs_tree->find(rs); diff --git a/src/os/bluestore/Btree2Allocator.h b/src/os/bluestore/Btree2Allocator.h index bccdeb6ad0571..21787bb6e621a 100644 --- a/src/os/bluestore/Btree2Allocator.h +++ b/src/os/bluestore/Btree2Allocator.h @@ -23,7 +23,7 @@ class Btree2Allocator : public Allocator { enum { RANGE_SIZE_BUCKET_COUNT = 14, }; - const ExtentCollectionTraits myTraits; + const LenPartitionedSetTraitsPow2 myTraits; public: // Making public to share with mempools