abstract_replication_strategy: calculate_effective_replication_map: optimize for static replication strategies

For replication strategies like "everywhere"
and "local" that return the same set of endpoints
for all tokens, we can call rs->calculate_natural_endpoints
one once and reuse the result for all token.

Note that ideally the replication_map could contain only
a single token range for this case, but that does't seem to work yet.

Add maybe_yield() calls to the tight loop
to prevent reactor stalls on large clusters when copying
a long vector returned by everywhere_replication_strategy
to potentially 1000's of tokens in the map.

Nicholas Peshek wrote in
https://github.com/scylladb/scylladb/issues/10337#issuecomment-1211152370

about similar patch by Geoffrey Beausire:
994c6ecf3c

> Yep. That dropped our startup from 3000+ seconds to about 40.

Fixes #10337

Signed-off-by: Benny Halevy <bhalevy@scylladb.com>
This commit is contained in:
Benny Halevy
2022-08-10 23:18:46 +03:00
parent eb678e723b
commit 9167b857e9

View File

@@ -308,10 +308,22 @@ abstract_replication_strategy::get_pending_address_ranges(const token_metadata_p
future<mutable_effective_replication_map_ptr> calculate_effective_replication_map(abstract_replication_strategy::ptr_type rs, token_metadata_ptr tmptr) {
replication_map replication_map;
const auto& sorted_tokens = tmptr->sorted_tokens();
for (const auto &t : tmptr->sorted_tokens()) {
auto eps = co_await rs->calculate_natural_endpoints(t, *tmptr);
replication_map.emplace(t, eps.get_vector());
if (!sorted_tokens.empty()) {
replication_map.reserve(sorted_tokens.size());
if (rs->natural_endpoints_depend_on_token()) {
for (const auto &t : sorted_tokens) {
auto eps = co_await rs->calculate_natural_endpoints(t, *tmptr);
replication_map.emplace(t, eps.get_vector());
}
} else {
auto eps = co_await rs->calculate_natural_endpoints(sorted_tokens.front(), *tmptr);
for (const auto &t : sorted_tokens) {
replication_map.emplace(t, eps.get_vector());
co_await coroutine::maybe_yield();
}
}
}
auto rf = rs->get_replication_factor(*tmptr);