From ab70b02d86288dc081e1b8a0a81ff8a84e74b793 Mon Sep 17 00:00:00 2001 From: Alexey Bashtanov Date: Thu, 15 Jan 2026 12:10:05 +0000 Subject: [PATCH] c/topic_table: use chunked_hash_map for lifecycle markers to avoid oversized allocations (cherry picked from commit efc8a8013cd693f2c11c20cdfc5092df269b2fff) --- src/v/cluster/archival/purger.cc | 5 +++-- src/v/cluster/controller_snapshot.h | 2 +- src/v/cluster/topic_table.cc | 3 ++- src/v/cluster/topic_table.h | 2 +- src/v/redpanda/admin/server.cc | 5 +++-- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/v/cluster/archival/purger.cc b/src/v/cluster/archival/purger.cc index 8f6f70250127d..b4889dac17547 100644 --- a/src/v/cluster/archival/purger.cc +++ b/src/v/cluster/archival/purger.cc @@ -25,6 +25,7 @@ #include "cluster/topics_frontend.h" #include "config/configuration.h" #include "config/node_config.h" +#include "container/chunked_hash_map.h" #include "hashing/xx.h" namespace { @@ -355,8 +356,8 @@ ss::future purger::run(run_quota_t quota) { } // Take a copy, as we will iterate over it asynchronously - cluster::topic_table::lifecycle_markers_t markers - = _topic_table.get_lifecycle_markers(); + chunked_vector + markers{std::from_range, _topic_table.get_lifecycle_markers()}; const auto my_global_position = get_global_position(); diff --git a/src/v/cluster/controller_snapshot.h b/src/v/cluster/controller_snapshot.h index ad17400834696..0665f3b768758 100644 --- a/src/v/cluster/controller_snapshot.h +++ b/src/v/cluster/controller_snapshot.h @@ -184,7 +184,7 @@ struct topics_t chunked_hash_map topics; raft::group_id highest_group_id; - absl::node_hash_map< + chunked_hash_map< nt_revision, nt_lifecycle_marker, nt_revision_hash, diff --git a/src/v/cluster/topic_table.cc b/src/v/cluster/topic_table.cc index eedac2fda7dd9..9a6ed5e78d2ee 100644 --- a/src/v/cluster/topic_table.cc +++ b/src/v/cluster/topic_table.cc @@ -1670,7 +1670,8 @@ ss::future<> topic_table::apply_snapshot( // Lifecycle markers is a simple static collection without notifications // etc, so we can just copy directly into place. - _lifecycle_markers = controller_snap.topics.lifecycle_markers; + _lifecycle_markers.replace( + controller_snap.topics.lifecycle_markers.values().copy()); reset_partitions_to_force_reconfigure( controller_snap.topics.partitions_to_force_recover); diff --git a/src/v/cluster/topic_table.h b/src/v/cluster/topic_table.h index 812a266371a90..b1dcf143a389e 100644 --- a/src/v/cluster/topic_table.h +++ b/src/v/cluster/topic_table.h @@ -424,7 +424,7 @@ class topic_table { topic_id_mapping_t _by_id; }; - using lifecycle_markers_t = absl::node_hash_map< + using lifecycle_markers_t = chunked_hash_map< nt_revision, nt_lifecycle_marker, nt_revision_hash, diff --git a/src/v/redpanda/admin/server.cc b/src/v/redpanda/admin/server.cc index e82b764591214..5efabc5182763 100644 --- a/src/v/redpanda/admin/server.cc +++ b/src/v/redpanda/admin/server.cc @@ -143,6 +143,7 @@ #include #include #include +#include #include #include #include @@ -4495,8 +4496,8 @@ admin_server::get_cloud_storage_lifecycle(std::unique_ptr) { auto& topic_table = _controller->get_topics_state().local(); - cluster::topic_table::lifecycle_markers_t markers - = topic_table.get_lifecycle_markers(); + chunked_vector + markers{std::from_range, topic_table.get_lifecycle_markers()}; // Hack: persuade json response to always include the field even if empty response.markers._set = true;