mirror of
https://github.com/scylladb/scylladb.git
synced 2026-04-22 17:40:34 +00:00
The algorithm used in `get_address_ranges` and `get_range_addresses` calls `calculate_natural_endpoints` in a loop; the loop iterates over all tokens in the token ring. If the complexity of a particular implementation of `calculate_natural_endpoints` is large - say `θ(n)`, where `n` is the number of tokens - this results in an `θ(n^2)` algorithm (or worse). This case happens for `Everywhere` replication strategy. For small clusters this doesn't matter that much, but if `n` is, say, `20*255`, this may result in huge reactor stalls, as observed in practice. We avoid these stalls by inserting tactical yields. We hope that some day someone actually implements a subquadratic algortihm here. The commit also adds a comment on `abstract_replication_strategy::calculate_natural_endpoints` explaining that the interface does not give a complexity guarantee (at this point); the different implementations have different complexities. For example, `Everywhere` implementation always iterates over all tokens in the token ring, so it has `θ(n)` worst and best case complexity. On the other hand, `NetworkTopologyStrategy` implementation usually finishes after visiting a small part of the token ring (specifically, as soon as it finds a token for each node in the ring) and performs a constant number of operations for each visited token on average, but theoretically its worst case complexity is actually `O(n + k^2)`, where `n` is the number of all tokens and `k` is the number of endpoints (the `k^2` appears since for each endpoint we must perform finds and inserts on `unordered_set` of size `O(k)`; `unordered_set` operations have `O(1)` average complexity but `O(size of the set)` worst case complexity). Therefore it's not easy to put any complexity guarantee in the interface at this point. Instead, we say that: - some implementations may yield - if their complexities force us to do so - but in general, there is no guarantee that the implementation may yield - e.g. the `Everywhere` implementation does not yield. Fixes #8555. Closes #8647