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...
ahupowerdns committed Oct 23, 2015
1 parent 326d399 commit ddb7e6c67244ae644c2acfcf58da55bff4a1ff13
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
@@ -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()
{
@@ -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.