]> granicus.if.org Git - pdns/commitdiff
speed up canonical ordering by a factor of 5, increasing the ugliness of the code...
authorbert hubert <bert.hubert@netherlabs.nl>
Fri, 23 Oct 2015 13:04:50 +0000 (15:04 +0200)
committerbert hubert <bert.hubert@netherlabs.nl>
Fri, 23 Oct 2015 13:04:50 +0000 (15:04 +0200)
pdns/dnsname.cc
pdns/dnsname.hh
pdns/test-dnsname_cc.cc

index 227363d65839a08a6a0ccc4af6ec716de1cf64c7..ffea62f2dd353713a061deb381c9a470308e69ee 100644 (file)
@@ -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()
 {
index 82ba34911bd5e6ae421cbe75f34c9950d0141c16..b0a571975fbe1514aca22df6cd739498baa6ea14 100644 (file)
@@ -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
index 5c78943e45683f710ac0d6220a995ce8f90c75e0..fdfa3016033c4705a60fc784bd449d75138f1487 100644 (file)
@@ -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);
 }