]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
os/bluestore/AvlAllocator: introduce bluestore_avl_alloc_ff_max_search_bytes 43747/head
authorKefu Chai <kchai@redhat.com>
Tue, 1 Jun 2021 11:14:33 +0000 (19:14 +0800)
committerMauricio Faria de Oliveira <mfo@canonical.com>
Wed, 10 Nov 2021 15:07:56 +0000 (12:07 -0300)
so AvlAllocator can switch from the first-first mode to best-fit mode
without walking through the whole space map tree. in the
highly-fragmented system, iterating the whole tree could hurt the
performance of fast storage system a lot.

the idea comes from openzfs's metaslab allocator.

Signed-off-by: Kefu Chai <kchai@redhat.com>
(cherry picked from commit 5a26875049d13130ffe5954428da0e1b9750359f)
Signed-off-by: Mauricio Faria de Oliveira <mfo@canonical.com>
 Conflicts:
src/common/options/global.yaml.in:
- Moved new option into src/common/options.cc

src/common/options.cc
src/os/bluestore/AvlAllocator.cc
src/os/bluestore/AvlAllocator.h

index e4fd613f7c22a097bfb85b2fdf82b7a41ecc18cb..4fa13e1076b3e0f1050630e4446dc6a732fcfbac 100644 (file)
@@ -4720,6 +4720,10 @@ std::vector<Option> get_global_options() {
     .set_default(100)
     .set_description("Search for this many ranges in first-fit mode before switching over to to best-fit mode. 0 to iterate through all ranges for required chunk."),
 
+    Option("bluestore_avl_alloc_ff_max_search_bytes", Option::TYPE_SIZE, Option::LEVEL_DEV)
+    .set_default(16_M)
+    .set_description("Maximum distance to search in first-fit mode before switching over to to best-fit mode. 0 to iterate through all ranges for required chunk."),
+
     Option("bluestore_avl_alloc_bf_threshold", Option::TYPE_UINT, Option::LEVEL_DEV)
     .set_default(131072)
     .set_description(""),
index 751e52d58175c109e081a2a9ffb18b00f5d95fa8..08ddc6b94a189e62045eac712d3a6aa901ec7b76 100644 (file)
@@ -35,6 +35,7 @@ uint64_t AvlAllocator::_pick_block_after(uint64_t *cursor,
 {
   const auto compare = range_tree.key_comp();
   uint32_t search_count = 0;
+  uint64_t search_bytes = 0;
   auto rs_start = range_tree.lower_bound(range_t{*cursor, size}, compare);
   for (auto rs = rs_start; rs != range_tree.end(); ++rs) {
     uint64_t offset = p2roundup(rs->start, align);
@@ -45,6 +46,10 @@ uint64_t AvlAllocator::_pick_block_after(uint64_t *cursor,
     if (max_search_count > 0 && ++search_count > max_search_count) {
       return -1ULL;
     }
+    if (search_bytes = rs->start - rs_start->start;
+       max_search_bytes > 0 && search_bytes > max_search_bytes) {
+      return -1ULL;
+    }
   }
   if (*cursor == 0) {
     // If we already started from beginning, don't bother with searching from beginning
@@ -60,6 +65,9 @@ uint64_t AvlAllocator::_pick_block_after(uint64_t *cursor,
     if (max_search_count > 0 && ++search_count > max_search_count) {
       return -1ULL;
     }
+    if (max_search_bytes > 0 && search_bytes + rs->start > max_search_bytes) {
+      return -1ULL;
+    }
   }
   return -1ULL;
 }
@@ -333,6 +341,8 @@ AvlAllocator::AvlAllocator(CephContext* cct,
     cct->_conf.get_val<uint64_t>("bluestore_avl_alloc_bf_free_pct")),
   max_search_count(
     cct->_conf.get_val<uint64_t>("bluestore_avl_alloc_ff_max_search_count")),
+  max_search_bytes(
+    cct->_conf.get_val<Option::size_t>("bluestore_avl_alloc_ff_max_search_bytes")),
   range_count_cap(max_mem / sizeof(range_seg_t)),
   cct(cct)
 {}
index 023c1a15255dded0be6a54893e40b1ca6e71d3d9..b535a22d4c1897d1e9b95e31440255d1bd74512f 100644 (file)
@@ -169,6 +169,12 @@ private:
    * becomes the performance limiting factor on high-performance storage.
    */
   const uint32_t max_search_count;
+  /*
+   * Maximum distance to search forward from the last offset, without this
+   * limit, fragmented device can see lots of iterations and _block_picker()
+   * becomes the performance limiting factor on high-performance storage.
+   */
+  const uint32_t max_search_bytes;
   /*
   * Max amount of range entries allowed. 0 - unlimited
   */