]> granicus.if.org Git - pdns/commitdiff
20% speedup or so in xfrLabel by implementing 'vstringtok' which only returns offsets
authorBert Hubert <bert.hubert@netherlabs.nl>
Wed, 29 Mar 2006 18:27:22 +0000 (18:27 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Wed, 29 Mar 2006 18:27:22 +0000 (18:27 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@643 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/dnswriter.cc
pdns/misc.hh

index dbcc339316e752d3e30e1401c797c9be94f60397..b0d099737732edcd7e64047eb2b9b100bdcf3a7d 100644 (file)
@@ -121,38 +121,38 @@ void DNSPacketWriter::xfrText(const string& text)
 // this is the absolute hottest function in the pdns recursor
 void DNSPacketWriter::xfrLabel(const string& label, bool compress)
 {
-  typedef vector<string> parts_t;
+  typedef vector<pair<unsigned int, unsigned int> > parts_t;
   parts_t parts;
-  stringtok(parts, label, ".");
+  vstringtok(parts, label, ".");
   
-  string enc;
   // d_stuff is amount of stuff that is yet to be written out - the dnsrecordheader for example
   unsigned int pos=d_content.size() + d_record.size() + d_stuff; 
   string chopped(label);
   
   for(parts_t::const_iterator i=parts.begin(); i!=parts.end(); ++i) {
     map<string, uint16_t>::iterator li;
-    if(compress && (li=d_labelmap.find(chopped))!=d_labelmap.end()) {   // see if we've written out this domain before
+    // see if we've written out this domain before
+    if(compress && (li=d_labelmap.find(chopped))!=d_labelmap.end()) {   
       uint16_t offset=li->second;
       offset|=0xc000;
-      enc.append(1, (char)(offset >> 8));
-      enc.append(1, (char)(offset & 0xff));
+      d_record.push_back((char)(offset >> 8));
+      d_record.push_back((char)(offset & 0xff));
       goto out;                                 // skip trailing 0 in case of compression
     }
     else if(compress || d_labelmap.count(chopped)) { // if 'compress' is true, li will be equal to d_labelmap.end()
       d_labelmap[chopped]=pos;                       //  if untrue, we need to count 
     }
-    enc.append(1, (char)i->length());
-    enc.append(*i);
-    pos+=i->length()+1;
+    d_record.push_back((char)(i->second - i->first));
+    unsigned int len=d_record.size();
+    d_record.resize(len + i->second - i->first);
+    memcpy(((&*d_record.begin()) + len), label.c_str() + i-> first, i->second - i->first);
+
+    pos+=(i->second - i->first)+1;
     chopOff(chopped);                   // www.powerdns.com -> powerdns.com -> com 
   }
-  enc.append(1,(char)0);
+  d_record.push_back(0);
 
  out:;
-
-  const uint8_t* ptr=reinterpret_cast<const uint8_t*>(enc.c_str());
-  d_record.insert(d_record.end(), ptr, ptr+enc.size());
 }
 
 void DNSPacketWriter::xfrBlob(const string& blob)
index 13187eb97d381c8d642ced1619165fb310e5b678..988c901d721bee4682f141dfa95fa4497380f080 100644 (file)
@@ -115,6 +115,36 @@ stringtok (Container &container, string const &in,
     i = j + 1;
   }
 }
+
+template <typename Container>
+void
+vstringtok (Container &container, string const &in,
+           const char * const delimiters = " \t\n")
+{
+  const string::size_type len = in.length();
+  string::size_type i = 0;
+  
+  while (i<len) {
+    // eat leading whitespace
+    i = in.find_first_not_of (delimiters, i);
+    if (i == string::npos)
+      return;   // nothing left but white space
+    
+    // find the end of the token
+    string::size_type j = in.find_first_of (delimiters, i);
+    
+    // push token
+    if (j == string::npos) {
+      container.push_back (make_pair(i, len));
+      return;
+    } else
+      container.push_back (make_pair(i, j));
+    
+    // set up for next loop
+    i = j + 1;
+  }
+}
+
 const string toLower(const string &upper);
 const string toLowerCanonic(const string &upper);
 bool IpToU32(const string &str, uint32_t *ip);