]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
os/bluestore: Improve fragmentation calculation
authorAdam Kupczyk <akupczyk@ibm.com>
Thu, 26 Jan 2023 12:21:28 +0000 (12:21 +0000)
committerAdam Kupczyk <akupczyk@ibm.com>
Wed, 22 Feb 2023 17:27:35 +0000 (18:27 +0100)
The fragmentation is calculated by giving value to each free chunk.
Simplified, byte chunk size X*2 is 1.1 more worth then byte in chunk size X.
This logic is not very useful when chunks are really large.
So, for large chunks (>8MB) we change value coefficient to 1.02.

Overall, the change is intended so split into large chunks will only slightly
increase fragmentation, but preserving the sharp increase of fragmentation when
small chunks start dominating.

Partially fixes: https://tracker.ceph.com/issues/58022

Signed-off-by: Adam Kupczyk <akupczyk@ibm.com>
src/os/bluestore/Allocator.cc

index 3008f9ce8fdb4b509edcca8db9eda05fb3082241..5725e720d6f56bf24c670d3039dc6770e81f7025 100644 (file)
@@ -190,8 +190,13 @@ void Allocator::release(const PExtentVector& release_vec)
 double Allocator::get_fragmentation_score()
 {
   // this value represents how much worth is 2X bytes in one chunk then in X + X bytes
-  static const double double_size_worth = 1.1 ;
-  std::vector<double> scales{1};
+  static const double double_size_worth_small = 1.2;
+  // chunks larger then 128MB are large enough that should be counted without penalty
+  static const double double_size_worth_huge = 1;
+  static const size_t small_chunk_p2 = 20; // 1MB
+  static const size_t huge_chunk_p2 = 27; // 128MB
+  // for chunks 1MB - 128MB penalty coeffs are linearly weighted 1.2 (at small) ... 1 (at huge)
+  static std::vector<double> scales{1};
   double score_sum = 0;
   size_t sum = 0;
 
@@ -199,9 +204,17 @@ double Allocator::get_fragmentation_score()
     size_t sc = sizeof(v) * 8 - std::countl_zero(v) - 1; //assign to grade depending on log2(len)
     while (scales.size() <= sc + 1) {
       //unlikely expand scales vector
-      scales.push_back(scales[scales.size() - 1] * double_size_worth);
+      auto ss = scales.size();
+      double scale = double_size_worth_small;
+      if (ss >= huge_chunk_p2) {
+       scale = double_size_worth_huge;
+      } else if (ss > small_chunk_p2) {
+       // linear decrease 1.2 ... 1
+       scale = (double_size_worth_huge * (ss - small_chunk_p2) + double_size_worth_small * (huge_chunk_p2 - ss)) /
+         (huge_chunk_p2 - small_chunk_p2);
+      }
+      scales.push_back(scales[scales.size() - 1] * scale);
     }
-
     size_t sc_shifted = size_t(1) << sc;
     double x = double(v - sc_shifted) / sc_shifted; //x is <0,1) in its scale grade
     // linear extrapolation in its scale grade