@@ -52,23 +52,41 @@ using P = BlueStore::printer;
5252
5353void Estimator::cleanup ()
5454{
55+ wctx = nullptr ;
5556 new_size = 0 ;
5657 uncompressed_size = 0 ;
5758 compressed_occupied = 0 ;
5859 compressed_size = 0 ;
60+ compressed_area = 0 ;
5961 total_uncompressed_size = 0 ;
6062 total_compressed_occupied = 0 ;
6163 total_compressed_size = 0 ;
6264 actual_compressed = 0 ;
6365 actual_compressed_plus_pad = 0 ;
6466 extra_recompress.clear ();
67+ single_compressed_blob = true ;
68+ last_blob = nullptr ;
6569}
70+
71+ void Estimator::set_wctx (const WriteContext* wctx)
72+ {
73+ this ->wctx = wctx;
74+ }
75+
6676inline void Estimator::batch (const BlueStore::Extent* e, uint32_t gain)
6777{
6878 const Blob *h_Blob = &(*e->blob );
6979 const bluestore_blob_t &h_bblob = h_Blob->get_blob ();
7080 if (h_bblob.is_compressed ()) {
81+ if (last_blob) {
82+ if (h_Blob != last_blob) {
83+ single_compressed_blob = false ;
84+ }
85+ } else {
86+ last_blob = h_Blob;
87+ }
7188 compressed_size += e->length * h_bblob.get_compressed_payload_length () / h_bblob.get_logical_length ();
89+ compressed_area += e->length ;
7290 compressed_occupied += gain;
7391 } else {
7492 uncompressed_size += e->length ;
@@ -82,6 +100,16 @@ inline bool Estimator::is_worth()
82100{
83101 uint32_t cost = uncompressed_size * expected_compression_factor +
84102 compressed_size * expected_recompression_error;
103+ if (uncompressed_size == 0 && single_compressed_blob) {
104+ // The special case if all extents are from compressed blobs.
105+ // We want to avoid the case of recompressing into exactly the same.
106+ // The cost should increase proportionally to blob size;
107+ // the rationale is that recompressing small blob is likely to provide gain,
108+ // but recompressing whole large blob isn't.
109+ uint64_t padding_size = p2nphase<uint64_t >(compressed_size, bluestore->min_alloc_size );
110+ uint32_t split_tax = padding_size * compressed_area / wctx->target_blob_size ;
111+ cost += split_tax;
112+ }
85113 uint32_t gain = uncompressed_size + compressed_occupied;
86114 double need_ratio = bluestore->cct ->_conf ->bluestore_recompression_min_gain ;
87115 bool take = gain > cost * need_ratio;
@@ -153,15 +181,13 @@ void Estimator::get_regions(std::vector<region_t>& regions)
153181}
154182
155183int32_t Estimator::split_and_compress (
156- CompressorRef compr,
157- uint32_t max_blob_size,
158184 ceph::buffer::list& data_bl,
159185 Writer::blob_vec& bd)
160186{
161187 uint32_t au_size = bluestore->min_alloc_size ;
162188 uint32_t size = data_bl.length ();
163189 ceph_assert (size > 0 );
164- uint32_t blobs = (size + max_blob_size - 1 ) / max_blob_size ;
190+ uint32_t blobs = (size + wctx-> target_blob_size - 1 ) / wctx-> target_blob_size ;
165191 uint32_t blob_size = p2roundup (size / blobs, au_size);
166192 std::vector<uint32_t > blob_sizes (blobs);
167193 for (auto & i: blob_sizes) {
@@ -179,10 +205,10 @@ int32_t Estimator::split_and_compress(
179205 // FIXME: memory alignment here is bad
180206 bufferlist t;
181207 std::optional<int32_t > compressor_message;
182- int r = compr ->compress (bd.back ().object_data , t, compressor_message);
208+ int r = wctx-> compressor ->compress (bd.back ().object_data , t, compressor_message);
183209 ceph_assert (r == 0 );
184210 bluestore_compression_header_t chdr;
185- chdr.type = compr ->get_type ();
211+ chdr.type = wctx-> compressor ->get_type ();
186212 chdr.length = t.length ();
187213 chdr.compressor_message = compressor_message;
188214 encode (chdr, bd.back ().disk_data );
@@ -872,7 +898,7 @@ void Scan::on_write_start(
872898 }
873899 if (left_it != extent_map->extent_map .begin ()) {
874900 --left_it; // left_walk points to processes extent
875- if (limit_left < left_it->logical_offset ) {
901+ if (limit_left <= left_it->logical_offset ) {
876902 dout (30 ) << " left maybe expand" << dendl;
877903 has_expanded |= maybe_expand_scan_range (left_it, left, right);
878904 }
0 commit comments