Skip to content

Commit 0e3400d

Browse files
committed
os/bluestore: refactor allocator's ExtentCollectionTraits
Signed-off-by: Igor Fedotov <[email protected]>
1 parent 55f65bd commit 0e3400d

File tree

4 files changed

+80
-47
lines changed

4 files changed

+80
-47
lines changed

src/os/bluestore/Allocator.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ void Allocator::FreeStateHistogram::record_extent(uint64_t alloc_unit,
284284
uint64_t off,
285285
uint64_t len)
286286
{
287-
size_t idx = myTraits._get_p2_size_bucket(len);
287+
size_t idx = myTraits._get_bucket(len);
288288
ceph_assert(idx < buckets.size());
289289
++buckets[idx].total;
290290

@@ -293,7 +293,7 @@ void Allocator::FreeStateHistogram::record_extent(uint64_t alloc_unit,
293293
auto delta = p2roundup(off, alloc_unit) - off;
294294
if (len >= delta + alloc_unit) {
295295
len -= delta;
296-
idx = myTraits._get_p2_size_bucket(len);
296+
idx = myTraits._get_bucket(len);
297297
ceph_assert(idx < buckets.size());
298298
++buckets[idx].aligned;
299299
buckets[idx].alloc_units += len / alloc_unit;
@@ -307,7 +307,7 @@ void Allocator::FreeStateHistogram::foreach(
307307
{
308308
size_t i = 0;
309309
for (const auto& b : buckets) {
310-
cb(myTraits._get_p2_size_bucket_max(i),
310+
cb(myTraits._get_bucket_max(i),
311311
b.total, b.aligned, b.alloc_units);
312312
++i;
313313
}

src/os/bluestore/Allocator.h

Lines changed: 71 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -24,34 +24,88 @@ typedef release_set_t::value_type release_set_entry_t;
2424
class Allocator {
2525
protected:
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,

src/os/bluestore/Btree2Allocator.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ int64_t Btree2Allocator::_allocate(
197197
continue;
198198
}
199199
}
200-
size_t bucket0 = myTraits._get_p2_size_bucket(want_now);
200+
size_t bucket0 = myTraits._get_bucket(want_now);
201201
int64_t r = __allocate(bucket0, want_now,
202202
unit, extents);
203203
if (r < 0) {
@@ -331,7 +331,7 @@ int64_t Btree2Allocator::__allocate(
331331
auto rs_p = _pick_block(0, rs_tree, size);
332332

333333
if (rs_p == rs_tree->end()) {
334-
auto bucket_center = myTraits._get_p2_size_bucket(weight_center);
334+
auto bucket_center = myTraits._get_bucket(weight_center);
335335

336336
// requested size is to the left of weight center
337337
// hence we try to search up toward it first
@@ -467,7 +467,7 @@ void Btree2Allocator::_remove_from_tree(
467467
uint64_t end)
468468
{
469469
range_seg_t rs(rt_p->first, rt_p->second);
470-
size_t bucket = myTraits._get_p2_size_bucket(rs.length());
470+
size_t bucket = myTraits._get_bucket(rs.length());
471471
range_size_tree_t* rs_tree = &range_size_set[bucket];
472472
auto rs_p = rs_tree->find(rs);
473473
ceph_assert(rs_p != rs_tree->end());
@@ -571,7 +571,7 @@ bool Btree2Allocator::__try_insert_range(
571571
void Btree2Allocator::_range_size_tree_add(const range_seg_t& rs) {
572572
auto l = rs.length();
573573
ceph_assert(rs.end > rs.start);
574-
size_t bucket = myTraits._get_p2_size_bucket(l);
574+
size_t bucket = myTraits._get_bucket(l);
575575
range_size_set[bucket].insert(rs);
576576
num_free += l;
577577

@@ -584,7 +584,7 @@ void Btree2Allocator::_range_size_tree_add(const range_seg_t& rs) {
584584
}
585585
void Btree2Allocator::_range_size_tree_rm(const range_seg_t& rs)
586586
{
587-
size_t bucket = myTraits._get_p2_size_bucket(rs.length());
587+
size_t bucket = myTraits._get_bucket(rs.length());
588588
range_size_tree_t* rs_tree = &range_size_set[bucket];
589589
ceph_assert(rs_tree->size() > 0);
590590
auto rs_p = rs_tree->find(rs);

src/os/bluestore/Btree2Allocator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class Btree2Allocator : public Allocator {
2323
enum {
2424
RANGE_SIZE_BUCKET_COUNT = 14,
2525
};
26-
const ExtentCollectionTraits myTraits;
26+
const LenPartitionedSetTraitsPow2 myTraits;
2727

2828
public:
2929
// Making public to share with mempools

0 commit comments

Comments
 (0)