From: Remi Gacogne Date: Tue, 22 Jul 2025 09:19:47 +0000 (+0200) Subject: dnsdist: Simplify the least outstanding policy X-Git-Tag: rec-5.4.0-alpha1~224^2~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=64eebe045c8fc05c0c28444d5205c867154ec5b3;p=thirdparty%2Fpdns.git dnsdist: Simplify the least outstanding policy The servers can no longer be updated under our feet, so we only need one pass. Signed-off-by: Remi Gacogne --- diff --git a/pdns/dnsdistdist/dnsdist-lbpolicies.cc b/pdns/dnsdistdist/dnsdist-lbpolicies.cc index f1de02ea18..4cdc57b023 100644 --- a/pdns/dnsdistdist/dnsdist-lbpolicies.cc +++ b/pdns/dnsdistdist/dnsdist-lbpolicies.cc @@ -31,44 +31,55 @@ static constexpr size_t s_staticArrayCutOff = 16; template using DynamicIndexArray = std::vector>; template using StaticIndexArray = std::array, s_staticArrayCutOff>; -template static std::optional getLeastOutstanding(const ServerPolicy::NumberedServerVector& servers, T& poss) +static std::optional getLeastOutstanding(const ServerPolicy::NumberedServerVector& servers) { - /* so you might wonder, why do we go through this trouble? The data on which we sort could change during the sort, - which would suck royally and could even lead to crashes. So first we snapshot on what we sort, and then we sort */ - size_t usableServers = 0; - for (const auto& d : servers) { - if (d.second->isUp()) { - poss.at(usableServers) = std::pair(std::tuple(d.second->outstanding.load(), d.second->d_config.order, d.second->getRelevantLatencyUsec()), d.first); - usableServers++; + std::optional best; + uint64_t leastOutstandingSeen = std::numeric_limits::max(); + int lowestOrderSeen = std::numeric_limits::max(); + double lowestLatencySeen = std::numeric_limits::max(); + + for (const auto& server : servers) { + if (!server.second->isUp()) { + continue; } - } - if (usableServers == 0) { - return std::nullopt; + auto outstanding = server.second->outstanding.load(); + auto order = server.second->d_config.order; + if (outstanding > leastOutstandingSeen) { + continue; + } + if (outstanding < leastOutstandingSeen) { + best = server.first; + leastOutstandingSeen = outstanding; + lowestOrderSeen = order; + lowestLatencySeen = server.second->getRelevantLatencyUsec(); + continue; + } + if (order > lowestOrderSeen) { + continue; + } + auto latency = server.second->getRelevantLatencyUsec(); + if (latency < lowestLatencySeen) { + best = server.first; + leastOutstandingSeen = outstanding; + lowestOrderSeen = order; + lowestLatencySeen = server.second->getRelevantLatencyUsec(); + } } - std::nth_element(poss.begin(), poss.begin(), poss.begin() + usableServers, [](const typename T::value_type& a, const typename T::value_type& b) { return a.first < b.first; }); - return poss.begin()->second; + return best; } // get server with least outstanding queries, and within those, with the lowest order, and within those: the fastest std::optional leastOutstanding(const ServerPolicy::NumberedServerVector& servers, const DNSQuestion* dq) { (void)dq; - using LeastOutstandingType = std::tuple; if (servers.size() == 1 && servers[0].second->isUp()) { return 1; } - if (servers.size() <= s_staticArrayCutOff) { - StaticIndexArray poss; - return getLeastOutstanding(servers, poss); - } - - DynamicIndexArray poss; - poss.resize(servers.size()); - return getLeastOutstanding(servers, poss); + return getLeastOutstanding(servers); } std::optional firstAvailable(const ServerPolicy::NumberedServerVector& servers, const DNSQuestion* dq)