From: Charles-Henri Bruyand Date: Tue, 19 Jun 2018 14:05:46 +0000 (+0200) Subject: dnsdist: consistent hash - get rid of intermediate map construction X-Git-Tag: dnsdist-1.3.3~148^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=93ca495f76a6bb21864f1e272f78998b56c15c78;p=thirdparty%2Fpdns.git dnsdist: consistent hash - get rid of intermediate map construction --- diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index a319d01f37..f7500f8f4b 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -754,44 +754,48 @@ shared_ptr whashed(const NumberedServerVector& servers, const D return valrandom(dq->qname->hash(g_hashperturb), servers, dq); } -/* - * @todo - * - test/benchmark other hashing methods - * - test/benchmark adding an avalanche algorithm on hashes - * @see https://github.com/haproxy/haproxy/blob/master/doc/internals/hashing.txt - */ - shared_ptr chashed(const NumberedServerVector& servers, const DNSQuestion* dq) { std::map> circle = {}; unsigned int qhash = dq->qname->hash(g_hashperturb); + unsigned int sel = 0, max = 0; + shared_ptr ret = nullptr, last = nullptr; for (const auto& d: servers) { if (d.second->isUp()) { + // make sure hashes have been computed if (d.second->hashes.empty()) { d.second->hash(); } { ReadLock rl(&(d.second->d_lock)); - for (const auto& h: d.second->hashes) { - // put server's hashes on the circle - circle.insert(std::make_pair(h, d.second)); + const auto& server = d.second; + // we want to keep track of the last hash + if (max < *(server->hashes.rbegin())) { + max = *(server->hashes.rbegin()); + last = server; + } + auto hash_it = server->hashes.begin(); + while (hash_it != server->hashes.end() + && *hash_it < qhash) { + if (*hash_it > sel) { + sel = *hash_it; + ret = server; + } + ++hash_it; } } } } - if (circle.empty()) { - return shared_ptr(); + if (ret != nullptr) { + return ret; } - - auto p = circle.upper_bound(qhash); - if(p == circle.end()) { - return circle.begin()->second; + if (last != nullptr) { + return last; } - return p->second; + return shared_ptr(); } - shared_ptr roundrobin(const NumberedServerVector& servers, const DNSQuestion* dq) { NumberedServerVector poss;