]> granicus.if.org Git - pdns/commitdiff
speed up DNSName hashing, create testcase for it. Close #2868
authorbert hubert <bert.hubert@netherlabs.nl>
Fri, 6 Nov 2015 12:14:30 +0000 (13:14 +0100)
committerbert hubert <bert.hubert@netherlabs.nl>
Fri, 6 Nov 2015 12:14:30 +0000 (13:14 +0100)
pdns/dnsname.cc
pdns/dnsname.hh
pdns/misc.hh
pdns/packetcache.hh
pdns/test-dnsname_cc.cc

index 65ca46e79274bb88cfd6f3cd0ad97e943e32c70e..0d5ee168cc0a65d00c8c2754e45562c91f161881 100644 (file)
@@ -264,8 +264,7 @@ bool DNSName::operator==(const DNSName& rhs) const
 
 size_t hash_value(DNSName const& d)
 {
-  boost::hash<string> hasher;
-  return hasher(toLower(d.toString())); // FIXME400 HACK - we rely on this lowercasing though in packetcache.hh
+  return d.hash();
 }
 
 string DNSName::escapeLabel(const std::string& label)
index 0822497971ebcd423758a7e82e4412365b9e46bc..c3016c6270c1cd5617cd7757d23023b712abf2e6 100644 (file)
@@ -6,6 +6,8 @@
 #include <strings.h>
 #include <stdexcept>
 
+uint32_t burtleCI(const unsigned char* k, uint32_t lengh, uint32_t init);
+
 // #include "dns.hh"
 // #include "logger.hh"
 
@@ -53,6 +55,10 @@ public:
   bool isRoot() const { return d_storage.size()==1 && d_storage[0]==0; }
   void clear() { d_storage.clear(); }
   void trimToLabels(unsigned int);
+  size_t hash() const
+  {
+    return burtleCI((const unsigned char*)d_storage.c_str(), d_storage.size(), 0);
+  }
   DNSName& operator+=(const DNSName& rhs)
   {
     if(d_storage.size() + rhs.d_storage.size() > 256) // reserve one byte for the root label
index 9dbad019bdd5683f8247c1e354e1c9417f2f70ea..3462c46beff32dec84cf4a3285439a975d71d6ec 100644 (file)
@@ -608,7 +608,6 @@ unsigned int getFilenumLimit(bool hardOrSoft=0);
 void setFilenumLimit(unsigned int lim);
 bool readFileIfThere(const char* fname, std::string* line);
 uint32_t burtle(const unsigned char* k, uint32_t lengh, uint32_t init);
-uint32_t burtleCI(const unsigned char* k, uint32_t lengh, uint32_t init);
 bool setSocketTimestamps(int fd);
 
 //! Sets the socket into blocking mode.
index 1a28689be11d7786293dddcfdf4ddb9249c69d68..2863b1d426ab33370b807f3af267810234827f2e 100644 (file)
@@ -126,7 +126,7 @@ private:
   vector<MapCombo> d_maps;
   MapCombo& getMap(const DNSName& qname) 
   {
-    return d_maps[hash_value(qname) % d_maps.size()];
+    return d_maps[qname.hash() % d_maps.size()];
   }
 
   AtomicCounter d_ops;
index c0b12f5e95a1660a4661574f1d8d4919a093e1ca..485fdb97852bbe4e1137c1ce8b17606b1e30ae96 100644 (file)
@@ -240,6 +240,31 @@ BOOST_AUTO_TEST_CASE(test_PacketParse) {
 }
 
 
+BOOST_AUTO_TEST_CASE(test_hash) {
+  DNSName a("wwW.Ds9A.Nl"), b("www.ds9a.nl");
+  BOOST_CHECK_EQUAL(a.hash(), b.hash());
+  
+  vector<uint32_t> counts(1500);
+  for(unsigned int n=0; n < 100000; ++n) {
+    DNSName dn(std::to_string(n)+"."+std::to_string(n*2)+"ds9a.nl");
+    DNSName dn2(std::to_string(n)+"."+std::to_string(n*2)+"Ds9a.nL");
+    BOOST_CHECK_EQUAL(dn.hash(), dn2.hash());
+    counts[dn.hash() % counts.size()]++;
+  }
+  
+  double sum = std::accumulate(std::begin(counts), std::end(counts), 0.0);
+  double m =  sum / counts.size();
+  
+  double accum = 0.0;
+  std::for_each (std::begin(counts), std::end(counts), [&](const double d) {
+      accum += (d - m) * (d - m);
+  });
+      
+  double stdev = sqrt(accum / (counts.size()-1));
+  BOOST_CHECK(stdev < 10);      
+}
+
 BOOST_AUTO_TEST_CASE(test_QuestionHash) {
   vector<unsigned char> packet;
   reportBasicTypes();