NULL,
PerfCountersBuilder::PRIO_DEBUGONLY,
unit_t(UNIT_BYTES));
+
+ b.add_u64_counter(l_bluestore_write_small_skipped,
+ "write_small_skipped",
+ "Small writes into existing or sparse small blobs skipped due to zero detection");
+ b.add_u64_counter(l_bluestore_write_small_skipped_bytes,
+ "write_small_skipped_bytes",
+ "Small writes into existing or sparse small blobs skipped due to zero detection (bytes)");
//****************************************
// compressions stats
// temporarily just pad them to min_alloc_size and write them to a new place
// on every update.
if (bdev->is_smr()) {
- BlobRef b = c->new_blob();
uint64_t b_off = p2phase<uint64_t>(offset, alloc_len);
uint64_t b_off0 = b_off;
- _pad_zeros(&bl, &b_off0, min_alloc_size);
o->extent_map.punch_hole(c, offset, length, &wctx->old_extents);
- wctx->write(offset, b, alloc_len, b_off0, bl, b_off, length, false, true);
+
+ // Zero detection -- small block
+ if (!bl.is_zero()) {
+ BlobRef b = c->new_blob();
+ _pad_zeros(&bl, &b_off0, min_alloc_size);
+ wctx->write(offset, b, alloc_len, b_off0, bl, b_off, length, false, true);
+ } else { // if (bl.is_zero())
+ dout(20) << __func__ << " skip small zero block " << std::hex
+ << " (0x" << b_off0 << "~" << bl.length() << ")"
+ << " (0x" << b_off << "~" << length << ")"
+ << std::dec << dendl;
+ logger->inc(l_bluestore_write_small_skipped);
+ logger->inc(l_bluestore_write_small_skipped_bytes, length);
+ }
+
return;
}
#endif
// due to existent extents
uint64_t b_off = offset - bstart;
uint64_t b_off0 = b_off;
- _pad_zeros(&bl, &b_off0, chunk_size);
+ o->extent_map.punch_hole(c, offset, length, &wctx->old_extents);
- dout(20) << __func__ << " reuse blob " << *b << std::hex
- << " (0x" << b_off0 << "~" << bl.length() << ")"
- << " (0x" << b_off << "~" << length << ")"
- << std::dec << dendl;
+ // Zero detection -- small block
+ if (!bl.is_zero()) {
+ _pad_zeros(&bl, &b_off0, chunk_size);
+
+ dout(20) << __func__ << " reuse blob " << *b << std::hex
+ << " (0x" << b_off0 << "~" << bl.length() << ")"
+ << " (0x" << b_off << "~" << length << ")"
+ << std::dec << dendl;
+
+ wctx->write(offset, b, alloc_len, b_off0, bl, b_off, length,
+ false, false);
+ logger->inc(l_bluestore_write_small_unused);
+ } else { // if (bl.is_zero())
+ dout(20) << __func__ << " skip small zero block " << std::hex
+ << " (0x" << b_off0 << "~" << bl.length() << ")"
+ << " (0x" << b_off << "~" << length << ")"
+ << std::dec << dendl;
+ logger->inc(l_bluestore_write_small_skipped);
+ logger->inc(l_bluestore_write_small_skipped_bytes, length);
+ }
- o->extent_map.punch_hole(c, offset, length, &wctx->old_extents);
- wctx->write(offset, b, alloc_len, b_off0, bl, b_off, length,
- false, false);
- logger->inc(l_bluestore_write_small_unused);
return;
}
}
offset0 + alloc_len,
min_alloc_size)) {
- uint64_t chunk_size = b->get_blob().get_chunk_size(block_size);
uint64_t b_off = offset - bstart;
uint64_t b_off0 = b_off;
- _pad_zeros(&bl, &b_off0, chunk_size);
+ o->extent_map.punch_hole(c, offset, length, &wctx->old_extents);
+
+ // Zero detection -- small block
+ if (!bl.is_zero()) {
+ uint64_t chunk_size = b->get_blob().get_chunk_size(block_size);
+ _pad_zeros(&bl, &b_off0, chunk_size);
- dout(20) << __func__ << " reuse blob " << *b << std::hex
- << " (0x" << b_off0 << "~" << bl.length() << ")"
- << " (0x" << b_off << "~" << length << ")"
- << std::dec << dendl;
+ dout(20) << __func__ << " reuse blob " << *b << std::hex
+ << " (0x" << b_off0 << "~" << bl.length() << ")"
+ << " (0x" << b_off << "~" << length << ")"
+ << std::dec << dendl;
+
+ wctx->write(offset, b, alloc_len, b_off0, bl, b_off, length,
+ false, false);
+ logger->inc(l_bluestore_write_small_unused);
+ } else { // if (bl.is_zero())
+ dout(20) << __func__ << " skip small zero block " << std::hex
+ << " (0x" << b_off0 << "~" << bl.length() << ")"
+ << " (0x" << b_off << "~" << length << ")"
+ << std::dec << dendl;
+ logger->inc(l_bluestore_write_small_skipped);
+ logger->inc(l_bluestore_write_small_skipped_bytes, length);
+ }
- o->extent_map.punch_hole(c, offset, length, &wctx->old_extents);
- wctx->write(offset, b, alloc_len, b_off0, bl, b_off, length,
- false, false);
- logger->inc(l_bluestore_write_small_unused);
return;
}
}
<< std::hex << offset << "~" << length
<< std::dec << dendl;
}
- // new blob.
- BlobRef b = c->new_blob();
uint64_t b_off = p2phase<uint64_t>(offset, alloc_len);
uint64_t b_off0 = b_off;
- _pad_zeros(&bl, &b_off0, block_size);
o->extent_map.punch_hole(c, offset, length, &wctx->old_extents);
- wctx->write(offset, b, alloc_len, b_off0, bl, b_off, length,
- min_alloc_size != block_size, // use 'unused' bitmap when alloc granularity
- // doesn't match disk one only
- true);
+
+ // Zero detection -- small block
+ if (!bl.is_zero()) {
+ // new blob.
+ BlobRef b = c->new_blob();
+ _pad_zeros(&bl, &b_off0, block_size);
+ wctx->write(offset, b, alloc_len, b_off0, bl, b_off, length,
+ min_alloc_size != block_size, // use 'unused' bitmap when alloc granularity
+ // doesn't match disk one only
+ true);
+ } else { // if (bl.is_zero())
+ dout(20) << __func__ << " skip small zero block " << std::hex
+ << " (0x" << b_off0 << "~" << bl.length() << ")"
+ << " (0x" << b_off << "~" << length << ")"
+ << std::dec << dendl;
+ logger->inc(l_bluestore_write_small_skipped);
+ logger->inc(l_bluestore_write_small_skipped_bytes, length);
+ }
return;
}