From: myoungwon oh Date: Mon, 19 Jan 2026 17:14:24 +0000 (+0900) Subject: crimson/os/seastore: optimize handling of batched requests X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=16023262acd854a5ffc7f95cf0b79d55a37340cf;p=ceph-ci.git crimson/os/seastore: optimize handling of batched requests During 4KB random write workloads, SeaStore receives batched dup_* entries in both omap_set_keys. This change enables efficient batch processing of these requests to reduce overhead. Signed-off-by: Myoungwon Oh --- diff --git a/src/crimson/os/seastore/omap_manager/log/log_manager.cc b/src/crimson/os/seastore/omap_manager/log/log_manager.cc index 9015067cddc..065c770e7fc 100644 --- a/src/crimson/os/seastore/omap_manager/log/log_manager.cc +++ b/src/crimson/os/seastore/omap_manager/log/log_manager.cc @@ -113,7 +113,62 @@ LogManager::omap_set_keys( } } } + std::map dup_kvs; + if (kvs.size() > BATCH_CREATE_SIZE) { + auto alloc_log_node = [&](laddr_t prev_laddr) + -> omap_set_key_iertr::future { + return tm.alloc_non_data_extent( + t, log_root.hint, LOG_NODE_BLOCK_SIZE + ).handle_error_interruptible( + crimson::ct_error::enospc::assert_failure{"unexpected enospc"}, + omap_set_key_iertr::pass_further{} + ).si_then([prev_laddr](auto ext) { + assert(ext); + ext->set_prev_addr(prev_laddr); + return omap_set_key_iertr::make_ready_future(ext); + }); + }; + + LogNodeRef e = co_await alloc_log_node(ext->get_laddr()); + LogNodeRef dup_e = co_await alloc_log_node( + co_await get_dup_addr_from_root(t, ext->get_laddr())); + for (auto &p : kvs) { + if (!is_log_key(p.first)) { + co_await remove_kv(t, log_root.addr, p.first, nullptr); + // reload latest log list e because e was updated if the key is in e + CachedExtentRef node; + Transaction::get_extent_ret ret; + ret = t.get_extent(e->get_paddr(), &node); + assert(ret == Transaction::get_extent_ret::PRESENT); + assert(node); + e = node->template cast(); + } + LogNodeRef cur = e; + if (is_dup_log_key(p.first)) { + cur = dup_e; + } + if (cur->expect_overflow(p.first.size(), p.second.length())) { + cur = co_await alloc_log_node(cur->get_laddr()); + if (!is_dup_log_key(p.first)) { + e = cur; + } else { + dup_e = cur; + } + } + cur->append_kv(t, p.first, p.second); + } + if (e->is_initial_pending()) { + e->set_dup_tail_addr(dup_e->get_laddr()); + } else { + auto mut = tm.get_mutable_extent(t, e)->cast(); + mut->set_dup_tail_addr(dup_e->get_laddr()); + } + log_root.update(e->get_laddr(), log_root.depth, + log_root.hint, log_root.type); + co_return; + } + for (auto &p : kvs) { if (is_ow_key(p.first) && has_ow_key) { continue; @@ -544,7 +599,6 @@ LogManager::omap_rm_keys( dup_keys.insert(std::move(nh)); } - // Deletion of pg_log_entry_t entries is performed by omap_rm_keys using a set. // For example, omap_rm_keys might be called with a set containing // pg_log_entry_t entries ranging from 0011.0001 to 0011.0010. diff --git a/src/crimson/os/seastore/omap_manager/log/log_manager.h b/src/crimson/os/seastore/omap_manager/log/log_manager.h index ce6b31e6c63..0c49de79cf7 100644 --- a/src/crimson/os/seastore/omap_manager/log/log_manager.h +++ b/src/crimson/os/seastore/omap_manager/log/log_manager.h @@ -17,6 +17,7 @@ namespace crimson::os::seastore::log_manager{ class LogNode; using LogNodeRef = TCachedExtentRef; constexpr uint8_t OW_SIZE = 2; +constexpr uint8_t BATCH_CREATE_SIZE = 50; /* * diff --git a/src/crimson/os/seastore/omap_manager/log/log_node.cc b/src/crimson/os/seastore/omap_manager/log/log_node.cc index 87de649d90e..02dd8f7c453 100644 --- a/src/crimson/os/seastore/omap_manager/log/log_node.cc +++ b/src/crimson/os/seastore/omap_manager/log/log_node.cc @@ -313,6 +313,8 @@ bool LogNode::expect_overflow(const std::string &key, gap -= d; } return remain < get_entry_size(ksize, vsize); + } else if (get_size() + reserved_size + 1 > d_bitmap_t::MAX_ENTRY) { + return true; } else if (is_ow_key(key) && !can_ow) { // guess there is enough space to store further entry in this node. // this makes sure that the last entry of this node is non-ow entry, diff --git a/src/crimson/os/seastore/omap_manager/log/log_node.h b/src/crimson/os/seastore/omap_manager/log/log_node.h index 2c200de466e..fcb57043e4e 100644 --- a/src/crimson/os/seastore/omap_manager/log/log_node.h +++ b/src/crimson/os/seastore/omap_manager/log/log_node.h @@ -244,6 +244,7 @@ constexpr uint32_t BITMAP_ARRAY_SIZE = ((LOG_NODE_BLOCK_SIZE / 4096) * 32 + 63) struct d_bitmap_t { uint64_t bitmap[BITMAP_ARRAY_SIZE] = {0}; static constexpr size_t BITS_PER_WORD = 64; + static constexpr size_t MAX_ENTRY = BITS_PER_WORD * BITMAP_ARRAY_SIZE; d_bitmap_t() = default; void set_bitmap(size_t bit) { @@ -918,6 +919,12 @@ struct LogNode int ow_gap_from_last_entry(const size_t key, const size_t val); bool expect_overflow(const std::string &key, size_t vsize, bool can_ow); + bool expect_overflow(size_t ksize, size_t vsize) const { + if (get_size() + reserved_size + 1 > d_bitmap_t::MAX_ENTRY) { + return true; + } + return free_space() < get_entry_size(ksize, vsize) + reserved_len; + } void update_delta() { if (!delta_buffer.empty()) {