mirror of
https://github.com/scylladb/scylladb.git
synced 2026-05-12 19:02:12 +00:00
locator: token_metadata: get rid of a quadratic behaviour in get_address_ranges()
Some callees of update_pending_ranges use the variant of get_address_ranges()
which builds a hashmap of all <endpoint, owned range> pairs. For
everywhere_topology, the size of this map is quadratic in the number of
endpoints, making it big enough to cause contiguous allocations of tens of MiB
for clusters of realistic size, potentially causing trouble for the
allocator (as seen e.g. in #12724). This deserves a correction.
This patch removes the quadratic variant of get_address_ranges() and replaces
its uses with its linear counterpart.
Refs #10337
Refs #10817
Refs #10836
Refs #10837
Fixes #12724
(cherry picked from commit 9e57b21e0c)
This commit is contained in:
committed by
Avi Kivity
parent
a8c49c44e5
commit
4ea67940cb
@@ -210,22 +210,6 @@ effective_replication_map::get_primary_ranges_within_dc(inet_address ep) const {
|
||||
});
|
||||
}
|
||||
|
||||
future<std::unordered_multimap<inet_address, dht::token_range>>
|
||||
abstract_replication_strategy::get_address_ranges(const token_metadata& tm) const {
|
||||
std::unordered_multimap<inet_address, dht::token_range> ret;
|
||||
for (auto& t : tm.sorted_tokens()) {
|
||||
dht::token_range_vector r = tm.get_primary_ranges_for(t);
|
||||
auto eps = co_await calculate_natural_endpoints(t, tm);
|
||||
rslogger.debug("token={}, primary_range={}, address={}", t, r, eps);
|
||||
for (auto ep : eps) {
|
||||
for (auto&& rng : r) {
|
||||
ret.emplace(ep, rng);
|
||||
}
|
||||
}
|
||||
}
|
||||
co_return ret;
|
||||
}
|
||||
|
||||
future<std::unordered_multimap<inet_address, dht::token_range>>
|
||||
abstract_replication_strategy::get_address_ranges(const token_metadata& tm, inet_address endpoint) const {
|
||||
std::unordered_multimap<inet_address, dht::token_range> ret;
|
||||
|
||||
@@ -118,7 +118,6 @@ public:
|
||||
future<dht::token_range_vector> get_ranges(inet_address ep, token_metadata_ptr tmptr) const;
|
||||
|
||||
public:
|
||||
future<std::unordered_multimap<inet_address, dht::token_range>> get_address_ranges(const token_metadata& tm) const;
|
||||
future<std::unordered_multimap<inet_address, dht::token_range>> get_address_ranges(const token_metadata& tm, inet_address endpoint) const;
|
||||
|
||||
// Caller must ensure that token_metadata will not change throughout the call.
|
||||
|
||||
@@ -779,13 +779,12 @@ void token_metadata_impl::calculate_pending_ranges_for_leaving(
|
||||
if (_leaving_endpoints.empty()) {
|
||||
return;
|
||||
}
|
||||
std::unordered_multimap<inet_address, dht::token_range> address_ranges = strategy.get_address_ranges(unpimplified_this).get0();
|
||||
// get all ranges that will be affected by leaving nodes
|
||||
std::unordered_set<range<token>> affected_ranges;
|
||||
for (auto endpoint : _leaving_endpoints) {
|
||||
auto r = address_ranges.equal_range(endpoint);
|
||||
for (auto x = r.first; x != r.second; x++) {
|
||||
affected_ranges.emplace(x->second);
|
||||
auto r = strategy.get_address_ranges(unpimplified_this, endpoint).get0();
|
||||
for (const auto& x : r) {
|
||||
affected_ranges.emplace(x.second);
|
||||
}
|
||||
}
|
||||
// for each of those ranges, find what new nodes will be responsible for the range when
|
||||
@@ -816,16 +815,14 @@ void token_metadata_impl::calculate_pending_ranges_for_replacing(
|
||||
if (_replacing_endpoints.empty()) {
|
||||
return;
|
||||
}
|
||||
auto address_ranges = strategy.get_address_ranges(unpimplified_this).get0();
|
||||
for (const auto& node : _replacing_endpoints) {
|
||||
auto existing_node = node.first;
|
||||
auto replacing_node = node.second;
|
||||
auto address_ranges = strategy.get_address_ranges(unpimplified_this, existing_node).get0();
|
||||
for (const auto& x : address_ranges) {
|
||||
seastar::thread::maybe_yield();
|
||||
if (x.first == existing_node) {
|
||||
tlogger.debug("Node {} replaces {} for range {}", replacing_node, existing_node, x.second);
|
||||
new_pending_ranges.emplace(x.second, replacing_node);
|
||||
}
|
||||
tlogger.debug("Node {} replaces {} for range {}", replacing_node, existing_node, x.second);
|
||||
new_pending_ranges.emplace(x.second, replacing_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user