Permalink
Browse files

speed up canonical ordering by a factor of 5, increasing the ugliness…

… of the code by a similar amount
  • Loading branch information...
1 parent 326d399 commit ddb7e6c67244ae644c2acfcf58da55bff4a1ff13 @ahupowerdns committed Oct 23, 2015
Showing with 88 additions and 7 deletions.
  1. +6 −5 pdns/dnsname.cc
  2. +77 −1 pdns/dnsname.hh
  3. +5 −1 pdns/test-dnsname_cc.cc
View
@@ -182,6 +182,12 @@ void DNSName::prependRawLabel(const std::string& label)
d_storage = prep+d_storage;
}
+bool DNSName::slowCanonCompare(const DNSName& rhs) const
+{
+ auto ours=getRawLabels(), rhsLabels = rhs.getRawLabels();
+ return std::lexicographical_compare(ours.rbegin(), ours.rend(), rhsLabels.rbegin(), rhsLabels.rend(), CIStringCompare());
+}
+
vector<string> DNSName::getRawLabels() const
{
vector<string> ret;
@@ -192,11 +198,6 @@ vector<string> DNSName::getRawLabels() const
return ret;
}
-bool DNSName::canonCompare(const DNSName& rhs) const
-{
- auto ours=getRawLabels(), rhsLabels = rhs.getRawLabels();
- return std::lexicographical_compare(ours.rbegin(), ours.rend(), rhsLabels.rbegin(), rhsLabels.rend(), CIStringCompare());
-}
bool DNSName::chopOff()
{
View
@@ -5,6 +5,7 @@
#include <deque>
#include <strings.h>
#include <stdexcept>
+
// #include "dns.hh"
// #include "logger.hh"
@@ -77,11 +78,12 @@ public:
ar & d_empty;
}
- bool canonCompare(const DNSName& rhs) const;
+ inline bool canonCompare(const DNSName& rhs) const;
private:
// typedef __gnu_cxx::__sso_string string_t;
typedef std::string string_t;
+ bool slowCanonCompare(const DNSName& rhs) const;
string_t d_storage;
bool d_empty;
int d_recurse;
@@ -93,6 +95,80 @@ private:
size_t hash_value(DNSName const& d);
+inline char dns2_tolower(char c)
+{
+ if(c>='A' && c<='Z')
+ c+='a'-'A';
+ return c;
+}
+
+
+inline bool DNSName::canonCompare(const DNSName& rhs) const
+{
+ // 01234567890abcd
+ // us: 1a3www4ds9a2nl
+ // rhs: 3www6online3com
+ // to compare, we start at the back, is nl < com? no -> done
+ //
+ // 0,2,6,a
+ // 0,4,a
+
+ uint8_t ourpos[64], rhspos[64];
+ uint8_t ourcount=0, rhscount=0;
+ //cout<<"Asked to compare "<<toString()<<" to "<<rhs.toString()<<endl;
+ for(const char* p = d_storage.c_str(); p < d_storage.c_str() + d_storage.size() && ourcount < sizeof(ourpos); p+=*p+1)
+ ourpos[ourcount++]=(p-d_storage.c_str());
+ for(const char* p = rhs.d_storage.c_str(); p < rhs.d_storage.c_str() + rhs.d_storage.size() && rhscount < sizeof(rhspos); p+=*p+1)
+ rhspos[rhscount++]=(p-rhs.d_storage.c_str());
+
+ if(ourcount == sizeof(ourpos) || rhscount==sizeof(rhspos)) {
+ return slowCanonCompare(rhs);
+ }
+
+ for(;;) {
+ if(ourcount == 0 && rhscount != 0)
+ return true;
+ if(ourcount == 0 && rhscount == 0)
+ return false;
+ if(ourcount !=0 && rhscount == 0)
+ return false;
+ ourcount--;
+ rhscount--;
+
+ /*
+ cout<<"Going to compare: '"<<string(d_storage.c_str() + ourpos[ourcount] + 1,
+ d_storage.c_str() + ourpos[ourcount] + 1 + *(d_storage.c_str() + ourpos[ourcount]))<<"'"<<endl;
+ cout<<"Against: '"<<string(rhs.d_storage.c_str() + rhspos[rhscount] + 1,
+ rhs.d_storage.c_str() + rhspos[rhscount] + 1 + *(rhs.d_storage.c_str() + rhspos[rhscount]))<<"'"<<endl;
+ */
+ bool res=std::lexicographical_compare(
+ d_storage.c_str() + ourpos[ourcount] + 1,
+ d_storage.c_str() + ourpos[ourcount] + 1 + *(d_storage.c_str() + ourpos[ourcount]),
+ rhs.d_storage.c_str() + rhspos[rhscount] + 1,
+ rhs.d_storage.c_str() + rhspos[rhscount] + 1 + *(rhs.d_storage.c_str() + rhspos[rhscount]),
+ [](const char& a, const char& b) {
+ return dns2_tolower(a) < dns2_tolower(b);
+ });
+
+ // cout<<"Forward: "<<res<<endl;
+ if(res)
+ return true;
+
+ res=std::lexicographical_compare( rhs.d_storage.c_str() + rhspos[rhscount] + 1,
+ rhs.d_storage.c_str() + rhspos[rhscount] + 1 + *(rhs.d_storage.c_str() + rhspos[rhscount]),
+ d_storage.c_str() + ourpos[ourcount] + 1,
+ d_storage.c_str() + ourpos[ourcount] + 1 + *(d_storage.c_str() + ourpos[ourcount]),
+ [](const char& a, const char& b) {
+ return dns2_tolower(a) < dns2_tolower(b);
+ });
+ // cout<<"Reverse: "<<res<<endl;
+ if(res)
+ return false;
+ }
+ return false;
+}
+
+
struct CanonDNSNameCompare: public std::binary_function<DNSName, DNSName, bool>
{
bool operator()(const DNSName&a, const DNSName& b) const
@@ -343,6 +343,9 @@ BOOST_AUTO_TEST_CASE(test_compare_canonical) {
DNSName lower("bert.com."), higher("alpha.nl.");
BOOST_CHECK(lower.canonCompare(higher));
+ BOOST_CHECK(DNSName("bert.com").canonCompare(DNSName("www.bert.com")));
+ BOOST_CHECK(DNSName("BeRt.com").canonCompare(DNSName("WWW.berT.com")));
+ BOOST_CHECK(!DNSName("www.BeRt.com").canonCompare(DNSName("WWW.berT.com")));
vector<DNSName> vec;
for(const std::string& a : {"bert.com.", "alpha.nl.", "articles.xxx.",
@@ -352,7 +355,7 @@ BOOST_AUTO_TEST_CASE(test_compare_canonical) {
}
sort(vec.begin(), vec.end(), CanonDNSNameCompare());
// for(const auto& v : vec)
- // cerr<<'"'<<v.toString()<<'"'<<endl;
+ // cerr<<'"'<<v.toString()<<'"'<<endl;
vector<DNSName> right;
for(const auto& a: {"bert.com.", "Aleph1.powerdns.com.",
@@ -364,6 +367,7 @@ BOOST_AUTO_TEST_CASE(test_compare_canonical) {
"yyy.XXX."})
right.push_back(DNSName(a));
+
BOOST_CHECK(vec==right);
}

0 comments on commit ddb7e6c

Please sign in to comment.