From: Remi Gacogne Date: Wed, 14 Mar 2018 17:28:25 +0000 (+0100) Subject: dnsdist: Don't copy data around in the exceed* functions X-Git-Tag: dnsdist-1.3.0~49^2~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=90b1e92f29a9b552a0489a947a97e03cc1d0399b;p=thirdparty%2Fpdns.git dnsdist: Don't copy data around in the exceed* functions --- diff --git a/pdns/dnsdist-lua-inspection.cc b/pdns/dnsdist-lua-inspection.cc index 2e21865054..e2c32cee45 100644 --- a/pdns/dnsdist-lua-inspection.cc +++ b/pdns/dnsdist-lua-inspection.cc @@ -24,10 +24,10 @@ #include "statnode.hh" -static std::unordered_map>> getGenResponses(unsigned int top, boost::optional labels, std::function pred) +static std::unordered_map>> getGenResponses(unsigned int top, boost::optional labels, std::function pred) { setLuaNoSideEffect(); - map counts; + map counts; unsigned int total=0; { std::lock_guard lock(g_rings.respMutex); @@ -53,7 +53,7 @@ static std::unordered_map>> getGenResp } } // cout<<"Looked at "<> rcounts; + vector> rcounts; rcounts.reserve(counts.size()); for(const auto& c : counts) rcounts.push_back(make_pair(c.second, c.first.makeLowerCase())); @@ -63,7 +63,7 @@ static std::unordered_map>> getGenResp return b.first < a.first; }); - std::unordered_map>> ret; + std::unordered_map>> ret; unsigned int count=1, rest=0; for(const auto& rc : rcounts) { if(count==top+1) @@ -75,20 +75,19 @@ static std::unordered_map>> getGenResp return ret; } -static map filterScore(const map& counts, - double delta, int rate) +static void filterScore(map& counts, + double delta, unsigned int rate) { - std::multimap score; - for(const auto& e : counts) - score.insert({e.second, e.first}); - - map ret; - double lim = delta*rate; - for(auto s = score.crbegin(); s != score.crend() && s->first > lim; ++s) { - ret[s->second]=s->first; + for(auto iter = counts.begin(); iter != counts.end();) { + if (iter->second <= lim) { + iter = counts.erase(iter); + } + else { + iter++; + } } - return ret; + } @@ -103,23 +102,23 @@ static void statNodeRespRing(statvisitor_t visitor, unsigned int seconds) cutoff.tv_sec -= seconds; } - std::lock_guard lock(g_rings.respMutex); - StatNode root; - for(const auto& c : g_rings.respRing) { - if (now < c.when) - continue; + { + std::lock_guard lock(g_rings.respMutex); + for(const auto& c : g_rings.respRing) { + if (now < c.when) + continue; - if (seconds && c.when < cutoff) - continue; + if (seconds && c.when < cutoff) + continue; - root.submit(c.name, c.dh.rcode, c.requestor); + root.submit(c.name, c.dh.rcode, c.requestor); + } } - StatNode::Stat node; - root.visit([&visitor](const StatNode* node_, const StatNode::Stat& self, const StatNode::Stat& children) { + StatNode::Stat node; + root.visit([visitor](const StatNode* node_, const StatNode::Stat& self, const StatNode::Stat& children) { visitor(*node_, self, children);}, node); - } static vector > > getRespRing(boost::optional rcode) @@ -142,7 +141,7 @@ static vector > > getRespRi } typedef map counts_t; -static map exceedRespGen(int rate, int seconds, std::function T) +static counts_t exceedRespGen(unsigned int rate, int seconds, std::function T) { counts_t counts; struct timespec cutoff, mintime, now; @@ -150,22 +149,26 @@ static map exceedRespGen(int rate, int seconds, std::function< cutoff = mintime = now; cutoff.tv_sec -= seconds; - std::lock_guard lock(g_rings.respMutex); - for(const auto& c : g_rings.respRing) { - if(seconds && c.when < cutoff) - continue; - if(now < c.when) - continue; - - T(counts, c); - if(c.when < mintime) - mintime = c.when; + { + std::lock_guard lock(g_rings.respMutex); + for(const auto& c : g_rings.respRing) { + if(seconds && c.when < cutoff) + continue; + if(now < c.when) + continue; + + T(counts, c); + if(c.when < mintime) + mintime = c.when; + } } + double delta = seconds ? seconds : DiffTime(now, mintime); - return filterScore(counts, delta, rate); + filterScore(counts, delta, rate); + return counts; } -static map exceedQueryGen(int rate, int seconds, std::function T) +static counts_t exceedQueryGen(unsigned int rate, int seconds, std::function T) { counts_t counts; struct timespec cutoff, mintime, now; @@ -173,22 +176,26 @@ static map exceedQueryGen(int rate, int seconds, std::function cutoff = mintime = now; cutoff.tv_sec -= seconds; - ReadLock rl(&g_rings.queryLock); - for(const auto& c : g_rings.queryRing) { - if(seconds && c.when < cutoff) - continue; - if(now < c.when) - continue; - T(counts, c); - if(c.when < mintime) - mintime = c.when; + { + ReadLock rl(&g_rings.queryLock); + for(const auto& c : g_rings.queryRing) { + if(seconds && c.when < cutoff) + continue; + if(now < c.when) + continue; + T(counts, c); + if(c.when < mintime) + mintime = c.when; + } } + double delta = seconds ? seconds : DiffTime(now, mintime); - return filterScore(counts, delta, rate); + filterScore(counts, delta, rate); + return counts; } -static map exceedRCode(int rate, int seconds, int rcode) +static counts_t exceedRCode(unsigned int rate, int seconds, int rcode) { return exceedRespGen(rate, seconds, [rcode](counts_t& counts, const Rings::Response& r) { @@ -197,7 +204,7 @@ static map exceedRCode(int rate, int seconds, int rcode) }); } -static map exceedRespByterate(int rate, int seconds) +static counts_t exceedRespByterate(unsigned int rate, int seconds) { return exceedRespGen(rate, seconds, [](counts_t& counts, const Rings::Response& r) { @@ -210,7 +217,7 @@ void setupLuaInspection() g_lua.writeFunction("topClients", [](boost::optional top_) { setLuaNoSideEffect(); auto top = top_.get_value_or(10); - map counts; + map counts; unsigned int total=0; { ReadLock rl(&g_rings.queryLock); @@ -219,7 +226,7 @@ void setupLuaInspection() total++; } } - vector> rcounts; + vector> rcounts; rcounts.reserve(counts.size()); for(const auto& c : counts) rcounts.push_back(make_pair(c.second, c.first)); @@ -241,7 +248,7 @@ void setupLuaInspection() g_lua.writeFunction("getTopQueries", [](unsigned int top, boost::optional labels) { setLuaNoSideEffect(); - map counts; + map counts; unsigned int total=0; if(!labels) { ReadLock rl(&g_rings.queryLock); @@ -260,7 +267,7 @@ void setupLuaInspection() } } // cout<<"Looked at "<> rcounts; + vector> rcounts; rcounts.reserve(counts.size()); for(const auto& c : counts) rcounts.push_back(make_pair(c.second, c.first.makeLowerCase())); @@ -270,7 +277,7 @@ void setupLuaInspection() return b.first < a.first; }); - std::unordered_map>> ret; + std::unordered_map>> ret; unsigned int count=1, rest=0; for(const auto& rc : rcounts) { if(count==top+1) diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index d8a8c916f2..9ad056fd8a 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -821,7 +821,7 @@ void setupLuaConfig(bool client) }); g_lua.writeFunction("addDynBlocks", - [](const map& m, const std::string& msg, boost::optional seconds, boost::optional action) { + [](const map& m, const std::string& msg, boost::optional seconds, boost::optional action) { setLuaSideEffect(); auto slow = g_dynblockNMG.getCopy(); struct timespec until, now;