@@ -24,34 +24,88 @@ typedef release_set_t::value_type release_set_entry_t;
2424class Allocator {
2525protected:
2626
27- struct ExtentCollectionTraits {
27+ /* *
28+ * This is a base set of traits for logical placing entries
29+ * into limited collection of buckets depending on their sizes.
30+ * Descandants should implement get_bucket(len) method to obtain
31+ * bucket index using entry length.
32+ */
33+ struct LenPartitionedSetTraits {
2834 size_t num_buckets;
29- size_t base_bits; // min extent size
30- size_t base = 1ull << base_bits;
31- size_t factor; // single bucket size range to be
32- // determined as [len, len * factor * 2)
33- // for log2(len) indexing and
34- // [len, len + factor * base)
35- // for linear indexing.
35+ size_t base_bits; // bits in min entry size
36+ size_t base; // min entry size
37+ size_t factor; // additional factor to be applied
38+ // to entry size when calculating
39+ // target bucket
3640
3741
38- ExtentCollectionTraits (size_t _num_buckets,
39- size_t _base_bits = 12 , // = 4096 bytes
40- size_t _factor = 1 ) :
42+ LenPartitionedSetTraits (size_t _num_buckets,
43+ size_t _base_bits = 12 , // = 4096 bytes
44+ size_t _factor = 1 ) :
4145 num_buckets (_num_buckets),
4246 base_bits (_base_bits),
4347 base (1ull << base_bits),
4448 factor (_factor)
4549 {
4650 ceph_assert (factor);
4751 }
52+ };
53+
54+ /* *
55+ * This extends LenPartitionedSetTraits to implement linear bucket indexing:
56+ * bucket index to be determined as entry's size divided by (base * factor),
57+ * i.e. buckets are:
58+ * [0..base)
59+ * [base, base+base*factor)
60+ * [base+base*factor, base+base*factor*2)
61+ * [base+base*factor*2, base+base*factor*3)
62+ * ...
63+ */
64+ struct LenPartitionedSetTraitsLinear : public LenPartitionedSetTraits {
65+ using LenPartitionedSetTraits::LenPartitionedSetTraits;
66+ /*
67+ * Determines bucket index for a given extent's length in a bucket set
68+ * with linear (len / base / factor) indexing.
69+ * The first bucket is targeted for lengths < base,
70+ * the last bucket is used for lengths above the maximum
71+ * detemined by bucket count.
72+ */
73+ inline size_t _get_bucket (uint64_t len) const {
74+ size_t idx = (len / factor) >> base_bits;
75+ idx = idx < num_buckets ? idx : num_buckets - 1 ;
76+ return idx;
77+ }
78+ /*
79+ * returns upper bound of a specific bucket
80+ */
81+ inline size_t _get_bucket_max (size_t bucket) const {
82+ return
83+ bucket < num_buckets - 1 ?
84+ base * factor * (1 + bucket) :
85+ std::numeric_limits<uint64_t >::max ();
86+ }
87+ };
4888
89+ /* *
90+ * This extends LenPartitionedSetTraits to implement exponential bucket indexing:
91+ * target bucket bounds are determined as
92+ * [0, base]
93+ * (base, base*2^factor]
94+ * (base*2^factor, base*2^(factor*2)]
95+ * (base*2^(factor*2), base*2^(factor*3)]
96+ * ...
97+ *
98+ */
99+ struct LenPartitionedSetTraitsPow2 : public LenPartitionedSetTraits {
49100 /*
50101 * Determines bucket index for a given extent's length in a bucket collection
51102 * with log2(len) indexing.
52- * The last bucket index is returned for lengths above the maximum.
103+ * The first bucket is targeted for lengths < base,
104+ * The last bucket index is used for lengths above the maximum
105+ * detemined by bucket count.
53106 */
54- inline size_t _get_p2_size_bucket (uint64_t len) const {
107+ using LenPartitionedSetTraits::LenPartitionedSetTraits;
108+ inline size_t _get_bucket (uint64_t len) const {
55109 size_t idx;
56110 const size_t len_p2_max =
57111 base << ((factor * (num_buckets - 2 )));
@@ -69,33 +123,12 @@ class Allocator {
69123 /*
70124 * returns upper bound of the bucket with log2(len) indexing.
71125 */
72- inline size_t _get_p2_size_bucket_max (size_t bucket) const {
126+ inline size_t _get_bucket_max (size_t bucket) const {
73127 return
74128 bucket < num_buckets - 1 ?
75129 base << (factor * bucket) :
76130 std::numeric_limits<uint64_t >::max ();
77- };
78-
79- /*
80- * Determines bucket index for a given extent's length in a bucket collection
81- * with linear (len / min_extent_size) indexing.
82- * The last bucket index is returned for lengths above the maximum.
83- */
84- inline size_t _get_linear_size_bucket (uint64_t len) const {
85- size_t idx = (len / factor) >> base_bits;
86- idx = idx < num_buckets ? idx : num_buckets - 1 ;
87- return idx;
88131 }
89- /*
90- * returns upper bound of the bucket with
91- * linear(len / min_extent_size) indexing.
92- */
93- inline size_t _get_linear_size_bucket_max (size_t bucket) const {
94- return
95- bucket < num_buckets - 1 ?
96- base * factor * (1 + bucket) :
97- std::numeric_limits<uint64_t >::max ();
98- };
99132 };
100133
101134 /*
@@ -145,7 +178,7 @@ class Allocator {
145178 * extents aren't not cached.
146179 */
147180 class OpportunisticExtentCache {
148- const Allocator::ExtentCollectionTraits myTraits;
181+ const LenPartitionedSetTraitsLinear myTraits;
149182 enum {
150183 BUCKET_COUNT = 16 ,
151184 EXTENTS_PER_BUCKET = 16 , // amount of entries per single bucket,
@@ -179,7 +212,7 @@ class Allocator {
179212 bool ret = false ;
180213 ceph_assert (p2aligned (offset, myTraits.base ));
181214 ceph_assert (p2aligned (len, myTraits.base ));
182- auto idx = myTraits._get_linear_size_bucket (len);
215+ auto idx = myTraits._get_bucket (len);
183216 if (idx < buckets.size ())
184217 ret = buckets[idx].try_put (offset);
185218 lock.unlock_shared ();
@@ -295,7 +328,7 @@ class Allocator {
295328 // - amount of allocation units in aligned extents
296329 //
297330 class FreeStateHistogram {
298- const Allocator::ExtentCollectionTraits myTraits;
331+ const LenPartitionedSetTraitsPow2 myTraits;
299332 enum {
300333 BASE_BITS = 12 , // 4096 bytes
301334 FACTOR = 2 ,
0 commit comments