77#include " BitmapAllocator.h"
88#include " AvlAllocator.h"
99#include " BtreeAllocator.h"
10+ #include " Btree2Allocator.h"
1011#include " HybridAllocator.h"
1112#include " common/debug.h"
1213#include " common/admin_socket.h"
14+
1315#define dout_subsys ceph_subsys_bluestore
1416using TOPNSPC::common::cmd_getval;
1517
@@ -108,7 +110,7 @@ class Allocator::SocketHook : public AdminSocketHook {
108110 } else if (command == " bluestore allocator fragmentation histogram " + name) {
109111 int64_t alloc_unit = 4096 ;
110112 cmd_getval (cmdmap, " alloc_unit" , alloc_unit);
111- if (alloc_unit = = 0 ||
113+ if (alloc_unit < = 0 ||
112114 p2align (alloc_unit, alloc->get_block_size ()) != alloc_unit) {
113115 ss << " Invalid allocation unit: '" << alloc_unit
114116 << " , to be aligned with: '" << alloc->get_block_size ()
@@ -123,20 +125,22 @@ class Allocator::SocketHook : public AdminSocketHook {
123125 return -EINVAL;
124126 }
125127
126- Allocator::FreeStateHistogram hist;
127- hist.resize (num_buckets);
128- alloc->build_free_state_histogram (alloc_unit, hist);
128+ Allocator::FreeStateHistogram hist (num_buckets);
129+ alloc->foreach (
130+ [&](size_t off, size_t len) {
131+ hist.record_extent (uint64_t (alloc_unit), off, len);
132+ });
129133 f->open_array_section (" extent_counts" );
130- for ( int i = 0 ; i < num_buckets; i++) {
131- f-> open_object_section ( " c " );
132- f->dump_unsigned ( " max_len " ,
133- hist[i]. get_max (i, num_buckets)
134- );
135- f->dump_unsigned (" total " , hist[i]. total );
136- f->dump_unsigned (" aligned " , hist[i]. aligned );
137- f->dump_unsigned ( " units " , hist[i]. alloc_units );
138- f-> close_section ();
139- }
134+ hist. foreach (
135+ [&]( uint64_t max_len, uint64_t total, uint64_t aligned, uint64_t units) {
136+ f->open_object_section ( " c " );
137+ f-> dump_unsigned ( " max_len " , max_len);
138+ f-> dump_unsigned ( " total " , total );
139+ f->dump_unsigned (" aligned " , aligned );
140+ f->dump_unsigned (" units " , units );
141+ f->close_section ( );
142+ }
143+ );
140144 f->close_section ();
141145 } else {
142146 ss << " Invalid command" << std::endl;
@@ -182,8 +186,13 @@ Allocator *Allocator::create(
182186 } else if (type == " btree" ) {
183187 return new BtreeAllocator (cct, size, block_size, name);
184188 } else if (type == " hybrid" ) {
185- return new HybridAllocator (cct, size, block_size,
189+ return new HybridAvlAllocator (cct, size, block_size,
190+ cct->_conf .get_val <uint64_t >(" bluestore_hybrid_alloc_mem_cap" ),
191+ name);
192+ } else if (type == " hybrid_btree2" ) {
193+ return new HybridBtree2Allocator (cct, size, block_size,
186194 cct->_conf .get_val <uint64_t >(" bluestore_hybrid_alloc_mem_cap" ),
195+ cct->_conf .get_val <double >(" bluestore_btree2_alloc_weight_factor" ),
187196 name);
188197 }
189198 if (alloc == nullptr ) {
@@ -195,7 +204,7 @@ Allocator *Allocator::create(
195204
196205void Allocator::release (const PExtentVector& release_vec)
197206{
198- interval_set< uint64_t > release_set;
207+ release_set_t release_set;
199208 for (auto e : release_vec) {
200209 release_set.insert (e.offset , e.length );
201210 }
@@ -266,50 +275,40 @@ double Allocator::get_fragmentation_score()
266275 return (ideal - score_sum) / (ideal - terrible);
267276}
268277
269- void Allocator::build_free_state_histogram (
270- size_t alloc_unit, Allocator::FreeStateHistogram& hist)
271- {
272- auto num_buckets = hist.size ();
273- ceph_assert (num_buckets);
274-
275- auto base = free_state_hist_bucket::base;
276- auto base_bits = free_state_hist_bucket::base_bits;
277- auto mux = free_state_hist_bucket::mux;
278- // maximum chunk size we track,
279- // provided by the bucket before the last one
280- size_t max =
281- free_state_hist_bucket::get_max (num_buckets - 2 , num_buckets);
282-
283- auto iterated_allocation = [&](size_t off, size_t len) {
284- size_t idx;
285- if (len <= base) {
286- idx = 0 ;
287- } else if (len > max) {
288- idx = num_buckets - 1 ;
289- } else {
290- size_t most_bit = cbits (uint64_t (len-1 )) - 1 ;
291- idx = 1 + ((most_bit - base_bits) / mux);
292- }
293- ceph_assert (idx < num_buckets);
294- ++hist[idx].total ;
278+ /* ************
279+ * Allocator::FreeStateHistogram
280+ *************/
281+ using std::function;
295282
296- // now calculate the bucket for the chunk after alignment,
297- // resulting chunks shorter than alloc_unit are discarded
298- auto delta = p2roundup (off, alloc_unit) - off;
299- if (len >= delta + alloc_unit) {
300- len -= delta;
301- if (len <= base) {
302- idx = 0 ;
303- } else if (len > max) {
304- idx = num_buckets - 1 ;
305- } else {
306- size_t most_bit = cbits (uint64_t (len-1 )) - 1 ;
307- idx = 1 + ((most_bit - base_bits) / mux);
308- }
309- ++hist[idx].aligned ;
310- hist[idx].alloc_units += len / alloc_unit;
311- }
312- };
283+ void Allocator::FreeStateHistogram::record_extent (uint64_t alloc_unit,
284+ uint64_t off,
285+ uint64_t len)
286+ {
287+ size_t idx = myTraits._get_bucket (len);
288+ ceph_assert (idx < buckets.size ());
289+ ++buckets[idx].total ;
313290
314- foreach (iterated_allocation);
291+ // now calculate the bucket for the chunk after alignment,
292+ // resulting chunks shorter than alloc_unit are discarded
293+ auto delta = p2roundup (off, alloc_unit) - off;
294+ if (len >= delta + alloc_unit) {
295+ len -= delta;
296+ idx = myTraits._get_bucket (len);
297+ ceph_assert (idx < buckets.size ());
298+ ++buckets[idx].aligned ;
299+ buckets[idx].alloc_units += len / alloc_unit;
300+ }
301+ }
302+ void Allocator::FreeStateHistogram::foreach (
303+ function<void (uint64_t max_len,
304+ uint64_t total,
305+ uint64_t aligned,
306+ uint64_t unit)> cb)
307+ {
308+ size_t i = 0 ;
309+ for (const auto & b : buckets) {
310+ cb (myTraits._get_bucket_max (i),
311+ b.total , b.aligned , b.alloc_units );
312+ ++i;
313+ }
315314}
0 commit comments